diff --git a/CODEOWNERS b/CODEOWNERS
index 3598264d0126154e0a84838f393fb3864f493dd7..fffaf64564e559bbf9ca4ffd5d5a65e228b26e00 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -98,7 +98,6 @@ zh-cn/application-dev/dfx/hitracechain-guidelines.md @zengyawen @stone2050 @stes
zh-cn/application-dev/dfx/errormanager-guidelines.md @littlejerry1 @ccllee @chengxingzhen @RayShih
zh-cn/application-dev/dfx/errormanager-guidelines.md @littlejerry1 @ccllee @chengxingzhen @RayShih
zh-cn/application-dev/key-features/multi-device-app-dev/ @lingminghw @crazyracing0726
-zh-cn/application-dev/database/ @ge-yafang @feng-aiwen @gong-a-shi @logic42
zh-cn/application-dev/napi/native-window-guidelines.md @ge-yafang @zhangqiang183 @zhouyaoying @zxg-gitee @nobuggers
zh-cn/application-dev/napi/mindspore-lite-guidelines.md @ge-yafang @principal87 @jianghui58
zh-cn/application-dev/napi/mindspore-lite-offline-model-guidelines.md @ge-yafang @principal87 @jianghui58
@@ -124,7 +123,7 @@ zh-cn/application-dev/device/sample-server-overview.md @ningningW @hughes802 @zh
zh-cn/application-dev/device/sample-server-guidelines.md @ningningW @hughes802 @zhangzhengxue @mamba-ting
zh-cn/application-dev/reference/arkui-js/ @HelloCrease @niulihua @tomatodevboy
zh-cn/application-dev/reference/arkui-ts/ @HelloCrease @niulihua @tomatodevboy
-zh-cn/application-dev/reference/native-lib @zengyawen @gongjunsong @liwentao_uiw @BlackStone
+zh-cn/application-dev/reference/native-lib @zengyawen @gongjunsong @liwentao_uiw @blackstone-oh
zh-cn/application-dev/quick-start/start-overview.md @ge-yafang
zh-cn/application-dev/quick-start/start-with-ets-stage.md @ge-yafang
zh-cn/application-dev/quick-start/start-with-ets-fa.md @ge-yafang
@@ -197,13 +196,13 @@ zh-cn/application-dev/reference/apis/js-apis-application-WindowExtensionAbility.
zh-cn/application-dev/application-models/windowextensionability.md @zhangqiang183 @ge-yafang @zhouyaoying @zxg-gitee @nobuggers
zh-cn/application-dev/reference/apis/js-apis-inner-application-windowExtensionContext.md @ge-yafang @zhouyaoying @zxg-gitee @nobuggers
zh-cn/application-dev/reference/apis/js-apis-appmanager.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
-zh-cn/application-dev/reference/apis/js-apis-arraylist.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-arraylist.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-audio.md @liuyuehua1 @zengyawen @magekkkk @currydavids
zh-cn/application-dev/reference/apis/js-apis-backgroundTaskManager.md @chenmingJay @ningningW @nan-xiansen @iceice1001
zh-cn/application-dev/reference/apis/js-apis-battery-info.md @aqxyjay @zengyawen @aqxyjay @alien0208
zh-cn/application-dev/reference/apis/js-apis-bluetooth.md @cheng_guohong @RayShih @cheng_guohong @quanli125
zh-cn/application-dev/reference/apis/js-apis-brightness.md @aqxyjay @zengyawen @aqxyjay @alien0208
-zh-cn/application-dev/reference/apis/js-apis-buffer.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-buffer.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-bundle-AbilityInfo.md @shuaytao @RayShih @wangzhen107 @inter515
zh-cn/application-dev/reference/apis/js-apis-bundle-ApplicationInfo.md @shuaytao @RayShih @wangzhen107 @inter515
zh-cn/application-dev/reference/apis/js-apis-bundle-BundleInfo.md @shuaytao @RayShih @wangzhen107 @inter515
@@ -232,7 +231,7 @@ zh-cn/application-dev/reference/apis/js-apis-Context.md @littlejerry1 @RayShih @
zh-cn/application-dev/reference/apis/js-apis-continuation-continuationExtraParams.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-continuation-continuationManager.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-continuation-continuationResult.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
-zh-cn/application-dev/reference/apis/js-apis-convertxml.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-convertxml.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-data-ability.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-dataShare.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-dataSharePredicates.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
@@ -242,13 +241,13 @@ zh-cn/application-dev/reference/apis/js-apis-data-preferences.md @feng-aiwen @ge
zh-cn/application-dev/reference/apis/js-apis-data-rdb.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-udmf.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-cloudData.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
-zh-cn/application-dev/reference/apis/js-apis-data-relationStore.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
+zh-cn/application-dev/reference/apis/js-apis-data-relationalStore.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-resultset.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-storage.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-data-ValuesBucket.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-dataAbilityHelper.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
zh-cn/application-dev/reference/apis/js-apis-DataUriUtils.md @feng-aiwen @ge-yafang @gong-a-shi @logic42
-zh-cn/application-dev/reference/apis/js-apis-deque.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-deque.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-device-info.md @mupceet @zengyawen @handyohos @nan-xiansen
zh-cn/application-dev/reference/apis/js-apis-device-manager.md @intermilano @RayShih @william-ligang @liuhonggang123
zh-cn/application-dev/reference/apis/js-apis-deviceUsageStatistics.md @shuaytao @RayShih @wangzhen107 @inter515
@@ -276,8 +275,8 @@ zh-cn/application-dev/reference/apis/js-apis-formhost.md @littlejerry1 @RayShih
zh-cn/application-dev/reference/apis/js-apis-formInfo.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-formprovider.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-geolocation.md @cheng_guohong @RayShih @cheng_guohong @xiangkejin123
-zh-cn/application-dev/reference/apis/js-apis-hashmap.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-hashset.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-hashmap.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-hashset.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-hiappevent.md @stone2050 @zengyawen @stesen @elsen-liu
zh-cn/application-dev/reference/apis/js-apis-hichecker.md @stone2050 @zengyawen @stesen @elsen-liu
zh-cn/application-dev/reference/apis/js-apis-hidebug.md @stone2050 @zengyawen @stesen @elsen-liu
@@ -301,11 +300,11 @@ zh-cn/application-dev/reference/apis/js-apis-inputmonitor.md @yuanxinying @ningn
zh-cn/application-dev/reference/apis/js-apis-intl.md @Buda-Liu @ningningW @mengjingzhimo @yangqing3
zh-cn/application-dev/reference/apis/js-apis-keycode.md @yuanxinying @ningningW @cococoler @alien0208
zh-cn/application-dev/reference/apis/js-apis-keyevent.md @yuanxinying @ningningW @cococoler @alien0208
-zh-cn/application-dev/reference/apis/js-apis-lightweightmap.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-lightweightset.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-linkedlist.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-list.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-logs.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-lightweightmap.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-lightweightset.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-linkedlist.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-list.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-logs.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-media.md @liuyuehua1 @zengyawen @xxb-wzy @currydavids
zh-cn/application-dev/reference/apis/js-apis-medialibrary.md @panqinxu @zengyawen @bubble_mao @jinhaihw
zh-cn/application-dev/reference/apis/js-apis-mediaquery.md @HelloCrease @niulihua @tomatodevboy
@@ -320,15 +319,15 @@ zh-cn/application-dev/reference/apis/js-apis-osAccount.md @nianCode @zengyawen @
zh-cn/application-dev/reference/apis/js-apis-particleAbility.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-pasteboard.md @han-zhengshi @ge-yafang @logic42
zh-cn/application-dev/reference/apis/js-apis-permissionrequestresult.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
-zh-cn/application-dev/reference/apis/js-apis-plainarray.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-plainarray.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-pointer.md @yuanxinying @ningningW @cococoler @alien0208
zh-cn/application-dev/reference/apis/js-apis-power.md @aqxyjay @zengyawen @aqxyjay @alien0208
zh-cn/application-dev/reference/apis/js-apis-privacyManager.md @nianCode @zengyawen @shuqinglin2 @jinhaihw
-zh-cn/application-dev/reference/apis/js-apis-process.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-process.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-processrunninginfo.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-processrunninginformation.md @littlejerry1 @RayShih @gwang2008 @chengxingzhen
zh-cn/application-dev/reference/apis/js-apis-prompt.md @HelloCrease @niulihua @tomatodevboy
-zh-cn/application-dev/reference/apis/js-apis-queue.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-queue.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-radio.md @zhang-hai-feng @zengyawen @jyh926 @gaoxi785
zh-cn/application-dev/reference/apis/js-apis-reminderAgent.md @jayleehw @RayShih @li-weifeng2 @currydavids
zh-cn/application-dev/reference/apis/js-apis-request.md @feng-aiwen @ningningW @nagexiucai @murphy1984
@@ -346,7 +345,7 @@ zh-cn/application-dev/reference/apis/js-apis-settings.md @xue-seu @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-sim.md @zhang-hai-feng @zengyawen @jyh926 @gaoxi785
zh-cn/application-dev/reference/apis/js-apis-sms.md @zhang-hai-feng @zengyawen @jyh926 @gaoxi785
zh-cn/application-dev/reference/apis/js-apis-socket.md @zhang-hai-feng @zengyawen @jyh926 @gaoxi785
-zh-cn/application-dev/reference/apis/js-apis-stack.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-stack.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-statfs.md @panqinxu @zengyawen @bubble_mao @jinhaihw
zh-cn/application-dev/reference/apis/js-apis-storage-statistics.md @panqinxu @zengyawen @bubble_mao @jinhaihw
zh-cn/application-dev/reference/apis/js-apis-system-app.md @HelloCrease @niulihua @tomatodevboy
@@ -376,22 +375,22 @@ zh-cn/application-dev/reference/apis/js-apis-system-vibrate.md @hellohyh001 @nin
zh-cn/application-dev/reference/apis/js-apis-telephony-data.md @zhang-hai-feng @zengyawen @jyh926 @gaoxi785
zh-cn/application-dev/reference/apis/js-apis-testRunner.md @inter515 @littlejerry1 @RayShih @inter515 @jiyong
zh-cn/application-dev/reference/apis/js-apis-thermal.md @aqxyjay @zengyawen @aqxyjay @alien0208
-zh-cn/application-dev/reference/apis/js-apis-timer.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-timer.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-touchevent.md @mayunteng_1 @ningningW @cococoler @alien0208
zh-cn/application-dev/reference/apis/js-apis-shortKey.md @mayunteng_1 @ningningW @cococoler @alien0208
zh-cn/application-dev/reference/apis/js-apis-devicestatus-cooperate.md @mayunteng_1 @ningningW @cococoler @alien0208
-zh-cn/application-dev/reference/apis/js-apis-treemap.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-treeset.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-treemap.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-treeset.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-uitest.md @inter515 @ningningW @inter515 @jiyong
zh-cn/application-dev/reference/apis/js-apis-update.md @hughes802 @ningningW @zhangzhengxue @mamba-ting
-zh-cn/application-dev/reference/apis/js-apis-uri.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-url.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-uri.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-url.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-usbManager.md @ge-yafang @Kevin-Lau @liuhonggang123
zh-cn/application-dev/reference/apis/js-apis-usb.md @ge-yafang @Kevin-Lau @liuhonggang123
zh-cn/application-dev/reference/apis/js-apis-usb-deprecated.md @ge-yafang @Kevin-Lau @liuhonggang123
zh-cn/application-dev/reference/apis/js-apis-useriam-userauth.md @gaoyong @zengyawen @niejiteng @jumozhanjiang
-zh-cn/application-dev/reference/apis/js-apis-util.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-vector.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-util.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-vector.md @gongjunsong @ge-yafang @flyingwolf @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-vibrator.md @hellohyh001 @ningningW @butterls @star-wind-snow-and-rain
zh-cn/application-dev/reference/apis/js-apis-volumemanager.md @panqinxu @zengyawen @bubble_mao @jinhaihw
zh-cn/application-dev/reference/apis/js-apis-wallpaper.md @feng-aiwen @ningningW @wangzhangjun @murphy1984
@@ -404,12 +403,12 @@ zh-cn/application-dev/reference/apis/js-apis-wifi.md @cheng_guohong @RayShih @ch
zh-cn/application-dev/reference/apis/js-apis-wifiext.md @cheng_guohong @RayShih @cheng_guohong @quanli125
zh-cn/application-dev/reference/apis/js-apis-window.md @zhangqiang183 @ge-yafang @zhouyaoying @zxg-gitee @nobuggers
zh-cn/application-dev/reference/apis/js-apis-windowAnimationManager.md @zhangqiang183 @ge-yafang @liuchao92 @zxg-gitee
-zh-cn/application-dev/reference/apis/js-apis-worker.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
-zh-cn/application-dev/reference/apis/js-apis-taskpool.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-worker.md @gongjunsong @ge-yafang @flyingwolf @weng-changcheng @blackstone-oh
+zh-cn/application-dev/reference/apis/js-apis-taskpool.md @gongjunsong @ge-yafang @flyingwolf @weng-changcheng @blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-workScheduler.md @chenmingJay @ningningW @nan-xiansen @iceice1001
zh-cn/application-dev/reference/apis/js-apis-inner-application-WorkSchedulerExtensionContext.md @chenmingJay @ningningW @nan-xiansen @iceice1001
zh-cn/application-dev/reference/apis/js-apis-WorkSchedulerExtensionAbility.md @chenmingJay @ningningW @nan-xiansen @iceice1001
-zh-cn/application-dev/reference/apis/js-apis-xml.md @gongjunsong @ge-yafang @flyingwolf @BlackStone
+zh-cn/application-dev/reference/apis/js-apis-xml.md @gongjunsong @ge-yafang @flyingwolf@blackstone-oh
zh-cn/application-dev/reference/apis/js-apis-zlib.md @shuaytao @RayShih @wangzhen107 @inter515
zh-cn/application-dev/reference/apis/js-apis-webview.md @bigpumpkin @HelloCrease @litao33 @zhang-xinyue15
zh-cn/application-dev/reference/arkui-ts/ts-basic-components-web.md @bigpumpkin @HelloCrease @litao33 @zhang-xinyue15
@@ -554,3 +553,37 @@ zh-cn/application-dev/reference/errorcodes/errorcode-webview.md @HelloCrease
zh-cn/application-dev/reference/errorcodes/errorcode-window.md @ge-yafang
zh-cn/application-dev/reference/errorcodes/errorcode-workScheduler.md @ningningW
zh-cn/application-dev/reference/errorcodes/errorcode-zlib.md @RayShih
+zh-cn/application-dev/reference/apis/js-apis-calendarManager.md @ge-yafang @jt_123456 @edollar
+zh-cn/application-dev/arkts-utils/arkts-commonlibrary-overview.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/concurrency-overview.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/async-concurrency-overview.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/single-io-development.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/cpu-intensive-task-development.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/io-intensive-task-development.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/sync-task-development.md @ge-yafang @gongjunsong @weng-changcheng @blackstone-oh
+zh-cn/application-dev/arkts-utils/container-overview.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/arkts-utils/linear-container.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/arkts-utils/nonlinear-container.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/arkts-utils/xml-overview.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/arkts-utils/xml-generation.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/arkts-utils/xml-parsing.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/arkts-utils/xml-conversion.md @ge-yafang @gongjunsong @blackstone-oh
+zh-cn/application-dev/database/data-mgmt-overview.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/app-data-persistence-overview.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-persistence-by-preferences.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-persistence-by-kv-store.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-persistence-by-rdb-store.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/sync-app-data-across-devices-overview.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-sync-of-rdb-store.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-sync-of-kv-store.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-reliability-security-overview.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-backup-and-restore.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-encryption.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/access-control-by-device-and-data-level.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/data-share-overview.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/unified-data-definition.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/share-data-by-datashareextensionability.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/share-data-by-silent-access.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
+zh-cn/application-dev/database/unified-data-channels.md @ge-yafang @feng-aiwen @gong-a-shi @logic42
\ No newline at end of file
diff --git a/en/OpenHarmony-Overview.md b/en/OpenHarmony-Overview.md
index 1aecb0171e73b02bcbcb9347497f594bf96c912e..16f95e959d2ec9c0d93d7421d4954f5ead748669 100644
--- a/en/OpenHarmony-Overview.md
+++ b/en/OpenHarmony-Overview.md
@@ -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|
Function Description and Use Case
| Application Scenario| Code Repository |
| -------- | -------- | -------- | -------- | -------- | -------- |
diff --git a/en/application-dev/IDL/idl-guidelines.md b/en/application-dev/IDL/idl-guidelines.md
index 102992de24a2879f9b08a5274058c2cdf4c0a280..7753e85d309ebbf350b7825a9ad3f76e3a3fcddf 100644
--- a/en/application-dev/IDL/idl-guidelines.md
+++ b/en/application-dev/IDL/idl-guidelines.md
@@ -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);
}
diff --git a/en/application-dev/Readme-EN.md b/en/application-dev/Readme-EN.md
index 5147d8c5200157e6a2edc8091630bbf22a6b9fb6..6e40eb34a50e798f7ae75f7c8cba2804cb6dfc51 100644
--- a/en/application-dev/Readme-EN.md
+++ b/en/application-dev/Readme-EN.md
@@ -50,6 +50,7 @@
- [\@BuilderParam Decorator: \@Builder Function Reference](quick-start/arkts-builderparam.md)
- [\@Styles Decorator: Definition of Resusable Styles](quick-start/arkts-style.md)
- [\@Extend Decorator: Extension of Built-in Components](quick-start/arkts-extend.md)
+ - [\@AnimatableExtend Decorator: Definition of Animatable Attributes](quick-start/arkts-animatable-extend.md)
- [stateStyles: Polymorphic Style](quick-start/arkts-statestyles.md)
- State Management
- [State Management Overview](quick-start/arkts-state-management-overview.md)
@@ -77,6 +78,7 @@
- Development
- [Application Models](application-models/Readme-EN.md)
- [UI Development](ui/Readme-EN.md)
+ - [ArkTS Common Library](arkts-utils/Readme-EN.md)
- [Web](web/Readme-EN.md)
- [Notification](notification/Readme-EN.md)
- [Window Manager](windowmanager/Readme-EN.md)
diff --git a/en/application-dev/ai/Readme-EN.md b/en/application-dev/ai/Readme-EN.md
index 525a9f3afe7e1e951d2216160cc23ba4c9b3335b..ac075993f5e8dc7ecba94e4f101f73005344b76f 100644
--- a/en/application-dev/ai/Readme-EN.md
+++ b/en/application-dev/ai/Readme-EN.md
@@ -1,3 +1,7 @@
# AI
-- [Using MindSpore Lite for Model Inference (JS)](mindspore-lite-js-guidelines.md)
+- [AI Development](ai-overview.md)
+- [Using MindSpore Lite JavaScript APIs to Develop AI Applications](mindspore-guidelines-based-js.md)
+- [Using MindSpore Lite Native APIs to Develop AI Applications](mindspore-guidelines-based-native.md)
+
+
diff --git a/en/application-dev/ai/ai-overview.md b/en/application-dev/ai/ai-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..968ee3439966cf2062e35cbb7929e4783566a2c6
--- /dev/null
+++ b/en/application-dev/ai/ai-overview.md
@@ -0,0 +1,40 @@
+# AI Development
+
+## Overview
+
+OpenHarmony provides native distributed AI capabilities. The AI subsystem consists of the following components:
+- MindSpore Lite: an AI inference framework that provides unified APIs for AI inference.
+- Neural Network Runtime (NNRt): an intermediate bridge that connects the inference framework and AI hardware.
+
+## MindSpore Lite
+
+MindSpore Lite is a built-in AI inference framework of OpenHarmony. It provides AI model inference capabilities for different hardware devices and end-to-end AI model inference solutions for developers to empower intelligent applications in all scenarios. Currently, MindSpore Lite has been widely used in applications such as image classification, target recognition, facial recognition, and character recognition.
+
+**Figure 1** Development process for MindSpore Lite model inference
+
+
+The MindSpore Lite development process consists of two phases:
+
+- Model conversion
+
+ MindSpore Lite uses models in `.ms` format for inference. You can use the model conversion tool provided by MindSpore Lite to convert third-party framework models, such as TensorFlow, TensorFlow Lite, Caffe, and ONNX, into `.ms` models. For details, see [Converting Models for Inference](https://www.mindspore.cn/lite/docs/en/r1.8/use/converter_tool.html).
+
+- Model inference
+
+ You can call the MindSpore Lite runtime APIs to implement model inference. The procedure is as follows:
+
+ 1. Create an inference context by setting the inference hardware and number of threads.
+ 2. Load the **.ms** model file.
+ 3. Set the model input data.
+ 4. Perform model inference, and read the output.
+
+MindSpore Lite is built in the OpenHarmony standard system as a system component. You can develop AI applications based on MindSpore Lite in the following ways:
+
+- Method 1: [Using MindSpore Lite JavaScript APIs to develop AI applications](./mindspore-guidelines-based-js.md). You directly call MindSpore Lite JavaScript APIs in the UI code to load the AI model and perform model inference. An advantage of this method is the quick verification of the inference effect.
+- Method 2: [Using MindSpore Lite native APIs to develop AI applications](./mindspore-guidelines-based-native.md). You encapsulate the algorithm models and the code for calling MindSpore Lite native APIs into a dynamic library, and then use N-API to encapsulate the dynamic library into JavaScript APIs for the UI to call.
+
+## Neural Network Runtime
+
+Neural Network Runtime (NNRt) functions as a bridge to connect the upper-layer AI inference framework and bottom-layer acceleration chip, implementing cross-chip inference computing of AI models.
+
+MindSpore Lite supports configuration of the NNRt backend, and therefore you can directly configure MindSpore Lite to use the NNRt hardware. The focus of this topic is about how to develop AI applications using MindSpore Lite. For details about how to use NNRt, see [Connecting the Neural Network Runtime to an AI Inference Framework](../napi/neural-network-runtime-guidelines.md).
diff --git a/en/application-dev/ai/figures/mindspore_workflow.png b/en/application-dev/ai/figures/mindspore_workflow.png
new file mode 100644
index 0000000000000000000000000000000000000000..babb4b4e1ec2b8961b79a324e3ac556fd1522e81
Binary files /dev/null and b/en/application-dev/ai/figures/mindspore_workflow.png differ
diff --git a/en/application-dev/ai/mindspore-lite-js-guidelines.md b/en/application-dev/ai/mindspore-guidelines-based-js.md
similarity index 62%
rename from en/application-dev/ai/mindspore-lite-js-guidelines.md
rename to en/application-dev/ai/mindspore-guidelines-based-js.md
index 1f309acf19ba608ac698892ed64bb2e75ffdc437..a504d6b2c9a1936b6408d76b3d5e34ed5da23db4 100644
--- a/en/application-dev/ai/mindspore-lite-js-guidelines.md
+++ b/en/application-dev/ai/mindspore-guidelines-based-js.md
@@ -1,10 +1,8 @@
-# Using MindSpore Lite for Model Inference (JS)
+# Using MindSpore Lite JavaScript APIs to Develop AI Applications
## Scenarios
-MindSpore Lite is an AI engine that implements AI model inference for different hardware devices. It has been used in a wide range of fields, such as image classification, target recognition, facial recognition, and character recognition.
-
-This document describes the general development process for implementing MindSpore Lite model inference. For details about how to use native APIs to implement model inference, see [Using MindSpore Lite for Model Inference](../napi/mindspore-lite-guidelines.md).
+You can use the JavaScript APIs provided by MindSpore Lite to directly integrate MindSpore Lite capabilities into the UI code. This way, you can quickly deploy AI algorithms for AI model inference.
## Basic Concepts
@@ -27,16 +25,14 @@ APIs involved in MindSpore Lite model inference are categorized into context API
## How to Develop
-The development process consists of the following main steps:
+Assume that you have prepared a model in the **.ms** format. The key steps in model inference are model reading, model building, model inference, and memory release. The development procedure is described as follows:
+
+1. Create a context, and set parameters such as the number of runtime threads and device type.
+2. Load the model. In this example, the model is read from the file.
+3. Load data. Before executing a model, you need to obtain the model input and then fill data in the input tensor.
+4. Perform model inference by calling **predict**, and read the output.
-1. Prepare the required model. You can download the required model directly or obtain the model by using the model conversion tool. The required data is read from the `bin` file.
- - If the downloaded model is in the `.ms` format, you can use it directly for inference. This document uses `mnet.caffemodel.ms` as an example.
- - If the downloaded model uses a third-party framework, such as TensorFlow, TensorFlow Lite, Caffe, or ONNX, you can use the [model conversion tool](https://www.mindspore.cn/lite/docs/en/r2.0/use/downloads.html#1-8-1) to convert it to the `.ms` format.
-2. Create a context, and set parameters such as the number of runtime threads and device type.
-3. Load the model. In this example, the model is read from the file.
-4. Load data. Before executing a model, you need to obtain the model input and then fill data in the input tensor.
-5. Perform inference and print the output. Call the **predict** API to perform model inference.
```js
@State inputName: string = 'mnet_caffemodel_nhwc.bin';
@State T_model_predict: string = 'Test_MSLiteModel_predict'
@@ -49,7 +45,6 @@ build() {
.fontSize(30)
.fontWeight(FontWeight.Bold)
.onClick(async () => {
- // 1. Prepare for a model.
let syscontext = globalThis.context;
syscontext.resourceManager.getRawFileContent(this.inputName).then((buffer) => {
this.inputBuffer = buffer;
@@ -57,20 +52,24 @@ build() {
}).catch(error => {
console.error('Failed to get buffer, error code: ${error.code},message:${error.message}.');
})
- // 2. Create a context.
+
+ // 1. Create a context.
let context: mindSporeLite.Context = {};
context.target = ['cpu'];
context.cpu = {}
context.cpu.threadNum = 1;
context.cpu.threadAffinityMode = 0;
context.cpu.precisionMode = 'enforce_fp32';
- // 3. Load the model.
+
+ // 2. Load the model.
let modelFile = '/data/storage/el2/base/haps/entry/files/mnet.caffemodel.ms';
let msLiteModel = await mindSporeLite.loadModelFromFile(modelFile, context);
- // 4. Load data.
+
+ // 3. Set the input data.
const modelInputs = msLiteModel.getInputs();
modelInputs[0].setData(this.inputBuffer.buffer);
- // 5. Perform inference and print the output.
+
+ // 4. Perform inference and print the output.
console.log('=========MSLITE predict start=====')
msLiteModel.predict(modelInputs).then((modelOutputs) => {
let output0 = new Float32Array(modelOutputs[0].getData());
@@ -89,21 +88,21 @@ build() {
## Debugging and Verification
-1. Connect to the rk3568 development board on DevEco Studio, click **Run entry**, and compile your own HAP. The following information is displayed:
+1. On DevEco Studio, connect to the device, click **Run entry**, and compile your own HAP. The following information is displayed:
```shell
Launching com.example.myapptfjs
$ hdc uninstall com.example.myapptfjs
- $ hdc install -r "D:\TVOS\JSAPI\MyAppTfjs\entry\build\default\outputs\default\entry-default-signed.hap"
+ $ hdc install -r "path/to/xxx.hap"
$ hdc shell aa start -a EntryAbility -b com.example.myapptfjs
```
-2. Use the hdc tool to connect to the rk3568 development board and push `mnet.caffemodel.ms` to the sandbox directory on the device. `mnet\_caffemodel\_nhwc.bin` is stored in the `rawfile` directory of the local project.
+2. Use hdc to connect to the device, and push **mnet.caffemodel.ms** to the sandbox directory on the device. **mnet\_caffemodel\_nhwc.bin** is stored in the **rawfile** directory of the local project.
```shell
- hdc -t 7001005458323933328a00bcdf423800 file send .\mnet.caffemodel.ms /data/app/el2/100/base/com.example.myapptfjs/haps/entry/files/
+ hdc -t your_device_id file send .\mnet.caffemodel.ms /data/app/el2/100/base/com.example.myapptfjs/haps/entry/files/
```
-3. Click **Test\_MSLiteModel\_predict** on the screen of the rk3568 development board to run the test case. The following information is displayed in the HiLog printing result:
+3. Click **Test\_MSLiteModel\_predict** on the device screen to run the test case. The following information is displayed in the HiLog printing result:
```shell
08-27 23:25:50.278 31782-31782/? I C03d00/JSAPP: =========MSLITE predict start=====
diff --git a/en/application-dev/ai/mindspore-guidelines-based-native.md b/en/application-dev/ai/mindspore-guidelines-based-native.md
new file mode 100644
index 0000000000000000000000000000000000000000..8294ad4c3213ecd7815962cb96751e2af72a77d5
--- /dev/null
+++ b/en/application-dev/ai/mindspore-guidelines-based-native.md
@@ -0,0 +1,244 @@
+# Using MindSpore Lite Native APIs to Develop AI Applications
+
+## Scenarios
+
+You can use the native APIs provided by MindSpore Lite to deploy AI algorithms and provides APIs for the UI layer to invoke the algorithms for model inference. A typical scenario is the AI SDK development.
+
+## Basic concepts
+
+- [N-API](../reference/native-lib/third_party_napi/napi.md): a set of native APIs used to build JavaScript components. N-APIs can be used to encapsulate libraries developed using C/C++ into JavaScript modules.
+
+## Preparing the Environment
+
+- Install DevEco Studio 3.1.0.500 or later, and update the SDK to API version 10 or later.
+
+## How to Develop
+
+1. Create a native C++ project.
+
+Open DevEco Studio, choose **File** > **New** > **Create Project** to create a native C++ template project. By default, the **entry/src/main/** directory of the created project contains the **cpp/** directory. You can store C/C++ code in this directory and provide JavaScript APIs for the UI layer to call the code.
+
+2. Compile the C++ inference code.
+
+Assume that you have prepared a model in the **.ms** format.
+
+Before using the Native APIs provided by MindSpore Lite for development, you need to reference the corresponding header files.
+
+```c
+#include
+#include
+#include
+#include
+```
+
+(1). Read model files.
+
+```C++
+void *ReadModelFile(NativeResourceManager *nativeResourceManager, const std::string &modelName, size_t *modelSize) {
+ auto rawFile = OH_ResourceManager_OpenRawFile(nativeResourceManager, modelName.c_str());
+ if (rawFile == nullptr) {
+ LOGE("Open model file failed");
+ return nullptr;
+ }
+ long fileSize = OH_ResourceManager_GetRawFileSize(rawFile);
+ void *modelBuffer = malloc(fileSize);
+ if (modelBuffer == nullptr) {
+ LOGE("Get model file size failed");
+ }
+ int ret = OH_ResourceManager_ReadRawFile(rawFile, modelBuffer, fileSize);
+ if (ret == 0) {
+ LOGI("Read model file failed");
+ OH_ResourceManager_CloseRawFile(rawFile);
+ return nullptr;
+ }
+ OH_ResourceManager_CloseRawFile(rawFile);
+ *modelSize = fileSize;
+ return modelBuffer;
+}
+```
+
+(2). Create a context, set parameters such as the number of threads and device type, and load the model.
+
+```c++
+OH_AI_ModelHandle CreateMSLiteModel(void *modelBuffer, size_t modelSize) {
+ // Create a context.
+ auto context = OH_AI_ContextCreate();
+ if (context == nullptr) {
+ DestroyModelBuffer(&modelBuffer);
+ LOGE("Create MSLite context failed.\n");
+ return nullptr;
+ }
+ auto cpu_device_info = OH_AI_DeviceInfoCreate(OH_AI_DEVICETYPE_CPU);
+ OH_AI_ContextAddDeviceInfo(context, cpu_device_info);
+
+ // Load the .ms model file.
+ auto model = OH_AI_ModelCreate();
+ if (model == nullptr) {
+ DestroyModelBuffer(&modelBuffer);
+ LOGE("Allocate MSLite Model failed.\n");
+ return nullptr;
+ }
+
+ auto build_ret = OH_AI_ModelBuild(model, modelBuffer, modelSize, OH_AI_MODELTYPE_MINDIR, context);
+ DestroyModelBuffer(&modelBuffer);
+ if (build_ret != OH_AI_STATUS_SUCCESS) {
+ OH_AI_ModelDestroy(&model);
+ LOGE("Build MSLite model failed.\n");
+ return nullptr;
+ }
+ LOGI("Build MSLite model success.\n");
+ return model;
+}
+```
+
+(3). Set the model input data, perform model inference, and obtain the output data.
+
+```js
+void RunMSLiteModel(OH_AI_ModelHandle model) {
+ // Set the model input data.
+ auto inputs = OH_AI_ModelGetInputs(model);
+ FillInputTensors(inputs);
+
+ auto outputs = OH_AI_ModelGetOutputs(model);
+
+ // Perform inference and print the output.
+ auto predict_ret = OH_AI_ModelPredict(model, inputs, &outputs, nullptr, nullptr);
+ if (predict_ret != OH_AI_STATUS_SUCCESS) {
+ OH_AI_ModelDestroy(&model);
+ LOGE("Predict MSLite model error.\n");
+ return;
+ }
+ LOGI("Run MSLite model success.\n");
+
+ LOGI("Get model outputs:\n");
+ for (size_t i = 0; i < outputs.handle_num; i++) {
+ auto tensor = outputs.handle_list[i];
+ LOGI("- Tensor %{public}d name is: %{public}s.\n", static_cast(i), OH_AI_TensorGetName(tensor));
+ LOGI("- Tensor %{public}d size is: %{public}d.\n", static_cast(i), (int)OH_AI_TensorGetDataSize(tensor));
+ auto out_data = reinterpret_cast(OH_AI_TensorGetData(tensor));
+ std::cout << "Output data is:";
+ for (int i = 0; (i < OH_AI_TensorGetElementNum(tensor)) && (i <= kNumPrintOfOutData); i++) {
+ std::cout << out_data[i] << " ";
+ }
+ std::cout << std::endl;
+ }
+ OH_AI_ModelDestroy(&model);
+}
+```
+
+
+(4). Implement a complete model inference process.
+
+```C++
+static napi_value RunDemo(napi_env env, napi_callback_info info)
+{
+ LOGI("Enter runDemo()");
+ GET_PARAMS(env, info, 2);
+ napi_value error_ret;
+ napi_create_int32(env, -1, &error_ret);
+
+ const std::string modelName = "ml_headpose.ms";
+ size_t modelSize;
+ auto resourcesManager = OH_ResourceManager_InitNativeResourceManager(env, argv[1]);
+ auto modelBuffer = ReadModelFile(resourcesManager, modelName, &modelSize);
+ if (modelBuffer == nullptr) {
+ LOGE("Read model failed");
+ return error_ret;
+ }
+ LOGI("Read model file success");
+
+ auto model = CreateMSLiteModel(modelBuffer, modelSize);
+ if (model == nullptr) {
+ OH_AI_ModelDestroy(&model);
+ LOGE("MSLiteFwk Build model failed.\n");
+ return error_ret;
+ }
+
+ RunMSLiteModel(model);
+
+ napi_value success_ret;
+ napi_create_int32(env, 0, &success_ret);
+
+ LOGI("Exit runDemo()");
+ return success_ret;
+}
+```
+
+(5). Write the **CMake** script to link the MindSpore Lite dynamic library `libmindspore_lite_ndk.so`.
+
+```cmake
+cmake_minimum_required(VERSION 3.4.1)
+project(OHOSMSLiteNapi)
+
+set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+
+include_directories(${NATIVERENDER_ROOT_PATH}
+ ${NATIVERENDER_ROOT_PATH}/include)
+
+add_library(mslite_napi SHARED mslite_napi.cpp)
+target_link_libraries(mslite_napi PUBLIC mindspore_lite_ndk) # MindSpore Lite dynamic library to link
+target_link_libraries(mslite_napi PUBLIC hilog_ndk.z)
+target_link_libraries(mslite_napi PUBLIC rawfile.z)
+target_link_libraries(mslite_napi PUBLIC ace_napi.z)
+```
+
+
+3. Use N-APIs to encapsulate C++ dynamic libraries into JavaScript modules.
+
+
+Create the **libmslite_api/** subdirectory in **entry/src/main/cpp/types/**, and create the **index.d.ts** file in the subdirectory. The file content is as follows:
+
+```js
+export const runDemo: (a:String, b:Object) => number;
+```
+
+Use the preceding code to define the JavaScript API `runDemo()`.
+
+In addition, add the **oh-package.json5** file to associate the API with the **.so** file to form a complete JavaScript module.
+
+```json
+{
+ "name": "libmslite_napi.so",
+ "types": "./index.d.ts"
+}
+```
+
+4. Invoke the encapsulated MindSpore module in the UI code.
+
+In **entry/src/ets/MainAbility/pages/index.ets**, define the **onClick()** event and call the encapsulated **runDemo()** API in the event callback.
+
+```js
+import msliteNapi from'libmslite_napi.so' // Import the msliteNapi module.
+
+// Certain code omitted
+
+// Trigger the event when the text on the UI is tapped.
+.onClick(() => {
+ resManager.getResourceManager().then(mgr => {
+ hilog.info(0x0000, TAG, '*** Start MSLite Demo ***');
+ let ret = 0;
+ ret = msliteNapi.runDemo("", mgr); // Call runDemo() to perform AI model inference.
+ if (ret == -1) {
+ hilog.info(0x0000, TAG, 'Error when running MSLite Demo!');
+ }
+ hilog.info(0x0000, TAG, '*** Finished MSLite Demo ***');
+ })
+})
+```
+
+## Debugging and Verification
+
+On DevEco Studio, connect to the device and click **Run entry**. The following log is generated for the application process:
+
+```text
+08-08 16:55:33.766 1513-1529/com.mslite.native_demo I A00000/MSLiteNativeDemo: *** Start MSLite Demo ***
+08-08 16:55:33.766 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: Enter runDemo()
+08-08 16:55:33.772 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: Read model file success
+08-08 16:55:33.799 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: Build MSLite model success.
+08-08 16:55:33.818 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: Run MSLite model success.
+08-08 16:55:33.818 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: Get model outputs:
+08-08 16:55:33.818 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: - Tensor 0 name is: output_node_0.
+08-08 16:55:33.818 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: - Tensor 0 size is: 12.
+08-08 16:55:33.826 1513-1529/com.mslite.native_demo I A00000/[MSLiteNapi]: Exit runDemo()
+08-08 16:55:33.827 1513-1529/com.mslite.native_demo I A00000/MSLiteNativeDemo: *** Finished MSLite Demo ***
+```
diff --git a/en/application-dev/application-dev-guide-for-gitee.md b/en/application-dev/application-dev-guide-for-gitee.md
index 2a5ff1426182d415f09b55868c48d4238974ba64..9770de4b35a7e23d38a0266e5e0daf826e656e00 100644
--- a/en/application-dev/application-dev-guide-for-gitee.md
+++ b/en/application-dev/application-dev-guide-for-gitee.md
@@ -25,7 +25,8 @@ All applications should be developed on top of these frameworks.
Then, equip yourself for developing the key features, with the following guidelines:
-- [Web](web/web-component-overview.md)
+- [ArkTS Common Library](arkts-utils/Readme-EN.md)
+- [Web](web/Readme-EN.md)
- [Notification](notification/Readme-EN.md)
- [Window Manager](windowmanager/Readme-EN.md)
- [WebGL](webgl/Readme-EN.md)
diff --git a/en/application-dev/application-dev-guide.md b/en/application-dev/application-dev-guide.md
index d8bf473f9527e26eaf61c1a19757623879c4ef1d..5aef516bfc51bbe842ecd6be64f2be3b0b7a1653 100644
--- a/en/application-dev/application-dev-guide.md
+++ b/en/application-dev/application-dev-guide.md
@@ -25,13 +25,14 @@ All applications should be developed on top of these frameworks.
Then, equip yourself for developing the key features, with the following guidelines:
+- [ArkTS Common Library](arkts-utils/arkts-commonlibrary-overview.md)
- [Web](web/web-component-overview.md)
- [Notification](notification/notification-overview.md)
- [Window Manager](windowmanager/window-overview.md)
- [WebGL](webgl/webgl-overview.md)
- [Media](media/media-application-overview.md)
- [Security](security/userauth-overview.md)
-- [AI](ai/mindspore-lite-js-guidelines.md)
+- [AI](ai/ai-overview.md)
- [Connectivity](connectivity/ipc-rpc-overview.md)
- [Telephony Service](telephony/telephony-overview.md)
- [Data Management](database/data-mgmt-overview.md)
diff --git a/en/application-dev/application-models/Readme-EN.md b/en/application-dev/application-models/Readme-EN.md
index 522a2d8e0de1280a26f0d416348aa665fd5062f6..7c320ef8068cd15bd0694f454c054b425d9841fd 100644
--- a/en/application-dev/application-models/Readme-EN.md
+++ b/en/application-dev/application-models/Readme-EN.md
@@ -21,6 +21,7 @@
- [EnterpriseAdminExtensionAbility](enterprise-extensionAbility.md)
- [InputMethodExtensionAbility](inputmethodextentionability.md)
- [WindowExtensionAbility (for System Applications Only)](windowextensionability.md)
+ - [DriverExtensionAbility](driverextensionability.md)
- Service Widget Development in Stage Model
- [Service Widget Overview](service-widget-overview.md)
- Developing an ArkTS Widget
@@ -43,6 +44,7 @@
- Widget Data Interaction
- [Widget Data Interaction Overview](arkts-ui-widget-interaction-overview.md)
- [Configuring a Widget to Update Periodically](arkts-ui-widget-update-by-time.md)
+ - [Updating Widget Content Through a Proxy](arkts-ui-widget-update-by-proxy.md)
- [Updating Local and Online Images in the Widget](arkts-ui-widget-image-update.md)
- [Updating Widget Content by State](arkts-ui-widget-update-by-status.md)
- [Updating Widget Content by Widget Host (for System Applications Only)](arkts-ui-widget-content-update.md)
@@ -59,10 +61,9 @@
- [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)
- - [Setting Atomic Services to Support Sharing](atomic-services-support-sharing.md)
- Process Model
- [Process Model Overview](process-model-stage.md)
- Common Events
diff --git a/en/application-dev/application-models/accessibilityextensionability.md b/en/application-dev/application-models/accessibilityextensionability.md
index a76742c142bfccdd015665478aadbaedf19ff39e..94c4429c5b2a4b49ba4dbae48f813dce16bba68a 100644
--- a/en/application-dev/application-models/accessibilityextensionability.md
+++ b/en/application-dev/application-models/accessibilityextensionability.md
@@ -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.
diff --git a/en/application-dev/application-models/application-context-stage.md b/en/application-dev/application-models/application-context-stage.md
index 17fe99577ab5cd782bcd4154274555bb8064da24..47fdeeedf1fe5238b0f0a2e56945be35208e0391 100644
--- a/en/application-dev/application-models/application-context-stage.md
+++ b/en/application-dev/application-models/application-context-stage.md
@@ -86,13 +86,13 @@ The application file paths obtained by the preceding contexts are different.
| Name| Path|
| -------- | -------- |
- | bundleCodeDir | \/el1/bundle/|
- | cacheDir | \/\/base/cache/|
- | filesDir | \/\/base/files/|
- | preferencesDir | \/\/base/preferences/|
- | tempDir | \/\/base/temp/|
- | databaseDir | \/\/database/|
- | distributedFilesDir | \/el2/distributedFiles/|
+ | bundleCodeDir | \/el1/bundle|
+ | cacheDir | \/\/base/cache|
+ | filesDir | \/\/base/files|
+ | preferencesDir | \/\/base/preferences|
+ | tempDir | \/\/base/temp|
+ | databaseDir | \/\/database|
+ | distributedFilesDir | \/el2/distributedFiles|
The sample code is as follows:
@@ -110,6 +110,9 @@ The application file paths obtained by the preceding contexts are different.
let distributedFilesDir = applicationContext.distributedFilesDir;
let preferencesDir = applicationContext.preferencesDir;
...
+ // Obtain the application file path.
+ let filePath = tempDir + 'test.txt';
+ console.info(`filePath: ${filePath}`);
}
}
```
@@ -118,13 +121,13 @@ The application file paths obtained by the preceding contexts are different.
| Name| Path|
| -------- | -------- |
- | bundleCodeDir | \/el1/bundle/|
- | cacheDir | \/\/base/**haps/\**/cache/|
- | filesDir | \/\/base/**haps/\**/files/|
- | preferencesDir | \/\/base/**haps/\**/preferences/|
- | tempDir | \/\/base/**haps/\**/temp/|
- | databaseDir | \/\/database/**\**/|
- | distributedFilesDir | \/el2/distributedFiles/**\**/|
+ | bundleCodeDir | \/el1/bundle|
+ | cacheDir | \/\/base/**haps/\**/cache|
+ | filesDir | \/\/base/**haps/\**/files|
+ | preferencesDir | \/\/base/**haps/\**/preferences|
+ | tempDir | \/\/base/**haps/\**/temp|
+ | databaseDir | \/\/database/**\**|
+ | distributedFilesDir | \/el2/distributedFiles/**\**|
The sample code is as follows:
@@ -141,6 +144,9 @@ The application file paths obtained by the preceding contexts are different.
let distributedFilesDir = this.context.distributedFilesDir;
let preferencesDir = this.context.preferencesDir;
...
+ // Obtain the application file path.
+ let filePath = tempDir + 'test.txt';
+ console.info(`filePath: ${filePath}`);
}
}
```
diff --git a/en/application-dev/application-models/arkts-ui-widget-configuration.md b/en/application-dev/application-models/arkts-ui-widget-configuration.md
index f0f003e608c995461ad1e84c65ed2a09b87febb7..d86c3b6991460a25c0ea6a177a8aec8c4607364c 100644
--- a/en/application-dev/application-models/arkts-ui-widget-configuration.md
+++ b/en/application-dev/application-models/arkts-ui-widget-configuration.md
@@ -16,7 +16,7 @@ Widget-related configuration includes **FormExtensionAbility** configuration and
"extensionAbilities": [
{
"name": "EntryFormAbility",
- "srcEntry": "./ets/entryformability/EntryFormAbility.ts",
+ "srcEntry": "./ets/entryformability/EntryFormAbility.ets",
"label": "$string:EntryFormAbility_label",
"description": "$string:EntryFormAbility_desc",
"type": "form",
@@ -42,9 +42,9 @@ Widget-related configuration includes **FormExtensionAbility** configuration and
| description | Description of the widget. The value can be a string or a resource index to descriptions in multiple languages. The value is a string with a maximum of 255 bytes.| String| Yes (initial value: left empty)|
| src | Full path of the UI code corresponding to the widget. For an ArkTS widget, the full path must contain the widget file name extension, for example, **./ets/widget/pages/WidgetCard.ets**. For a JS widget, the full path does not need to contain the widget file name extension, for example, **./js/widget/pages/WidgetCard**.| String| No|
| uiSyntax | Type of the widget. - **arkts**: ArkTS widget - **hml**: JS widget| String| Yes (initial value: **hml**)|
- | window | Window-related configurations.| Object| Yes|
+ | window | Window-related configurations.| Object| YYes (initial value: see Table 2)|
| isDefault | Whether the widget is a default one. Each UIAbility has only one default widget. - **true**: The widget is the default one. - **false**: The widget is not the default one.| Boolean| No|
- | colorMode | Color mode of the widget. - **auto**: auto-adaptive color mode - **dark**: dark color mode - **light**: light color mode| String| Yes (initial value: **auto**)|
+ | colorMode | Color mode of the widget. - **auto**: following the system color mode - **dark**: dark color mode - **light**: light color mode| String| Yes (initial value: **auto**)|
| supportDimensions | Grid styles supported by the widget. - **1 * 2**: indicates a grid with one row and two columns. - **2 * 2**: indicates a grid with two rows and two columns. - **2 * 4**: indicates a grid with two rows and four columns. - **4 * 4**: indicates a grid with four rows and four columns.| String array| No|
| defaultDimension | Default grid style of the widget. The value must be available in the **supportDimensions** array of the widget.| String| No|
| updateEnabled | Whether the widget can be updated periodically. - **true**: The widget can be updated at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used. - **false**: The widget cannot be updated periodically.| Boolean| No|
@@ -54,7 +54,14 @@ 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. - **true**: The widget supports the update-through-proxy feature. - **false**: The widget does not support the update-through-proxy feature. 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. - **true**: The widget is a dynamic widget. - **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. - **true**: The widget is a dynamic widget. - **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
+
+ | Field| Description| Data Type| Default Value Allowed|
+ | -------- | -------- | -------- | -------- |
+ | designWidth | Baseline width for page design. The size of an element is scaled by the actual device width.| Number| Yes (initial value: **720px**)|
+ | autoDesignWidth | Whether to automatically calculate the baseline width for page design. If it is set to **true**, the **designWidth** attribute will be ignored, and the baseline width will be calculated based on the device width and screen density.| Boolean| Yes (initial value: **false**)|
Example configuration:
diff --git a/en/application-dev/application-models/arkts-ui-widget-page-animation.md b/en/application-dev/application-models/arkts-ui-widget-page-animation.md
index 0cb8e356c61155d367e55c0f39bbf491d03e2e12..ff479a47e17cadc04c38ecdc3931b5aa1b3d687f 100644
--- a/en/application-dev/application-models/arkts-ui-widget-page-animation.md
+++ b/en/application-dev/application-models/arkts-ui-widget-page-animation.md
@@ -1,7 +1,7 @@
# Using Animations in the Widget
-To make your ArkTS widget more engaging, you can apply animations to it, including [explicit animation](../reference/arkui-ts/ts-explicit-animation.md), [attribute animation](../reference/arkui-ts/ts-animatorproperty.md), and [component transition](../reference/arkui-ts/ts-transition-animation-component.md). Just note the following restrictions when using the animations in ArkTS widgets.
+To make your ArkTS widget more engaging, you can apply animations to it, including [explicit animation](../reference/arkui-ts/ts-explicit-animation.md), [property animation](../reference/arkui-ts/ts-animatorproperty.md), and [component transition](../reference/arkui-ts/ts-transition-animation-component.md). Just note the following restrictions when using the animations in ArkTS widgets.
**Table 1** Restrictions on animation parameters
diff --git a/en/application-dev/application-models/arkts-ui-widget-update-by-proxy.md b/en/application-dev/application-models/arkts-ui-widget-update-by-proxy.md
index c655582af7834992c42025823b94ecab71eaa4ab..b7c1c93d21ec24673b3d07c4e971eadd7cd13661 100644
--- a/en/application-dev/application-models/arkts-ui-widget-update-by-proxy.md
+++ b/en/application-dev/application-models/arkts-ui-widget-update-by-proxy.md
@@ -89,7 +89,7 @@ The update-through-proxy configuration varies by the type of shared data.
}
```
-- In the widget page code file **widgets.abc**, use the variable in LocalStorage to obtain the subscribed data. The variable in LocalStorage is bound to a string and updates the subscribed data in the key:value pair format. The key must be the same as that subscribed to by the widget provider. In this example, the subscribed data is obtained through **'detail'** and displayed in the **\** component.
+- In the [widget page code file](arkts-ui-widget-creation.md), use the variable in LocalStorage to obtain the subscribed data. The variable in LocalStorage is bound to a string and updates the subscribed data in the key:value pair format. The key must be the same as that subscribed to by the widget provider. In this example, the subscribed data is obtained through **'detail'** and displayed in the **\** component.
```ts
let storage = new LocalStorage();
@Entry(storage)
@@ -178,7 +178,7 @@ The update-through-proxy configuration varies by the type of shared data.
}
```
-- In the widget page code file (generally the .ets file in the **pages** folder under the widget directory of the project), use the variable in LocalStorage to obtain the subscribed data. The variable in LocalStorage is bound to a string and updates the subscribed data in the key:value pair format. The key must be the same as that subscribed to by the widget provider. In the example, the subscribed data is obtained through **'list'**, and the value of the first element is displayed on the **\** component.
+- In the [widget page code file](arkts-ui-widget-creation.md), use the variable in LocalStorage to obtain the subscribed data. The variable in LocalStorage is bound to a string and updates the subscribed data in the key:value pair format. The key must be the same as that subscribed to by the widget provider. In the example, the subscribed data is obtained through **'list'**, and the value of the first element is displayed on the **\** component.
```ts
let storage = new LocalStorage();
@Entry(storage)
@@ -215,4 +215,4 @@ The update-through-proxy configuration varies by the type of shared data.
## Data Provider Development
-For details, see [Data Management](../database/data-mgmt-overview.md).
+For details, see [Data Management](../database/share-data-by-silent-access.md).
diff --git a/en/application-dev/application-models/arkts-ui-widget-working-principles.md b/en/application-dev/application-models/arkts-ui-widget-working-principles.md
index b1b09dc409380da8e530f571b2e5711ec63edd10..a8599ca8827c2d41c3ff1be032151c1f6debead9 100644
--- a/en/application-dev/application-models/arkts-ui-widget-working-principles.md
+++ b/en/application-dev/application-models/arkts-ui-widget-working-principles.md
@@ -15,10 +15,11 @@
- Widget rendering service: a service that manages widget rendering instances. Widget rendering instances are bound to the [widget components](../reference/arkui-ts/ts-basic-components-formcomponent.md) on the widget host on a one-to-one basis. The widget rendering service runs the widget page code **widgets.abc** for rendering, and sends the rendered data to the corresponding widget component on the widget host.
- **Figure 2** Working principles of the ArkTS widget rendering service
-
+ **Figure 2** Working principles of the ArkTS widget rendering service
-Unlike JS widgets, ArkTS widgets support logic code running. The widget page code **widgets.abc** is executed by the widget rendering service, which is managed by the Widget Manager. Each widget component of a widget host corresponds to a rendering instance in the widget rendering service. Rendering instances of a widget provider run in the same virtual machine operating environment, and rendering instances of different widget providers run in different virtual machine operating environments. In this way, the resources and state data are isolated between widgets of different widget providers. During development, pay attention to the use of the [globalThis](uiability-data-sync-with-ui.md#using-globalthis-between-uiability-and-page) object. Use one **globalThis** object for widgets from the same widget provider, and different **globalThis** objects for widgets from different widget providers.
+ 
+
+Unlike JS widgets, ArkTS widgets support logic code execution. The widget page code **widgets.abc** is executed by the widget rendering service, which is managed by the Widget Manager. Each widget component of a widget host corresponds to a rendering instance in the widget rendering service. Rendering instances of a widget provider run in the same virtual machine operating environment, and rendering instances of different widget providers run in different virtual machine operating environments. In this way, the resources and state data are isolated between widgets of different widget providers. During development, pay attention to the use of the [globalThis](uiability-data-sync-with-ui.md#using-globalthis-between-uiability-and-ui-page) object. Use one **globalThis** object for widgets from the same widget provider, and different **globalThis** objects for widgets from different widget providers.
## Advantages of ArkTS Widgets
@@ -34,7 +35,7 @@ As a quick entry to applications, ArkTS widgets outperform JS widgets in the fol

- More widget features
- - Animation: ArkTS widgets support the [attribute animation](../reference/arkui-ts/ts-animatorproperty.md) and [explicit animation](../reference/arkui-ts/ts-explicit-animation.md) capabilities, which can be leveraged to deliver a more engaging experience.
+ - Animation: ArkTS widgets support the [property animation](../reference/arkui-ts/ts-animatorproperty.md) and [explicit animation](../reference/arkui-ts/ts-explicit-animation.md) capabilities, which can be leveraged to deliver a more engaging experience.
- Custom drawing: ArkTS widgets allow you to draw graphics with the [\](../reference/arkui-ts/ts-components-canvas-canvas.md) component to present information more vividly.
- Logic code execution: The capability to run logic code in widgets means that service logic can be self-closed in widgets, expanding the use cases of widgets.
@@ -57,6 +58,8 @@ In addition, ArkTS widgets do not support the following features:
- Instant preview
-- Breakpoint debugging.
+- Breakpoint debugging
- Hot reload
+
+- **setTimeOut**
diff --git a/en/application-dev/application-models/atomic-services-support-sharing.md b/en/application-dev/application-models/atomic-services-support-sharing.md
deleted file mode 100644
index ba99573b28c4e25ef5ed2c8ca472e559a00f4713..0000000000000000000000000000000000000000
--- a/en/application-dev/application-models/atomic-services-support-sharing.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Setting Atomic Services to Support Sharing
-## How to Develop
-
-1. An application calls [UIAbility.onShare()](../reference/apis/js-apis-app-ability-uiAbility.md#onshare), a lifecycle callback provided by the UIAbility component, to set the data to share. In this lifecycle callback, **ohos.extra.param.key.contentTitle** indicates the title of the content to share in the sharing box, **ohos.extra.param.key.shareAbstract** provides an abstract description of the content, and **ohos.extra.param.key.shareUrl** indicates the online address of the service. You need to set these three items as objects, with the key set to **title**, **abstract**, and **url**, respectively.
-
- ```ts
- import AbilityConstant from '@ohos.app.ability.AbilityConstant';
- class MyUIAbility extends UIAbility {
- onShare(wantParams) {
- console.log('onShare');
- wantParams['ohos.extra.param.key.contentTitle'] = {title: "OA"};
- wantParams['ohos.extra.param.key.shareAbstract'] = {abstract: "communication for company employee"};
- wantParams['ohos.extra.param.key.shareUrl'] = {url: "oa.example.com"};
- }
- }
- ```
-
-2. A system dialog box calls [abilityManager.acquireShareData()](../reference/apis/js-apis-app-ability-abilityManager.md#acquiresharedata) to obtain data shared through atomic service sharing. Specifically, the system finds the UIAbility based on the mission ID and calls the **OnShare()** lifecycle of the UIAbility to obtain the shared data.
-
- ```ts
- import abilityManager from '@ohos.app.ability.abilityManager';
- try {
- abilityManager.acquireShareData(1, (err, wantParam) => {
- if (err) {
- console.error(`acquireShareData fail, err: ${JSON.stringify(err)}`);
- } else {
- console.log(`acquireShareData success, data: ${JSON.stringify(wantParam)}`);
- }
- });
- } catch (paramError) {
- console.error(`error.code: ${JSON.stringify(paramError.code)}, error.message: ${JSON.stringify(paramError.message)}`);
- }
- ```
diff --git a/en/application-dev/application-models/component-startup-rules.md b/en/application-dev/application-models/component-startup-rules.md
index bddf63dbc69ea243733e6f60f67f92a854833bf7..2db47d35f24df7d3eb155bb4ab2540f4a1af7ce0 100644
--- a/en/application-dev/application-models/component-startup-rules.md
+++ b/en/application-dev/application-models/component-startup-rules.md
@@ -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

-
diff --git a/en/application-dev/application-models/context-switch.md b/en/application-dev/application-models/context-switch.md
index 53047adb03ff8508f1428f62a4f6d982fedc0aeb..fe2051bcb244c10771bde056a4152da59838a6b7 100644
--- a/en/application-dev/application-models/context-switch.md
+++ b/en/application-dev/application-models/context-switch.md
@@ -10,7 +10,7 @@
| [getBundleName(callback : AsyncCallback<string>): void;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7) [getBundleName(): Promise<string>;](../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<bundle.DisplayOrientation>): void;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7) [getDisplayOrientation(): Promise<bundle.DisplayOrientation>;](../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<void>):void;](../reference/apis/js-apis-inner-app-context.md#contextsetdisplayorientation7) [setDisplayOrientation(orientation:bundle.DisplayOrientation):Promise<void>;](../reference/apis/js-apis-inner-app-context.md#contextsetdisplayorientation7-1) | \@ohos.screen.d.ts | [setOrientation(orientation: Orientation, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-screen.md#setorientation) [setOrientation(orientation: Orientation): Promise<void>;](../reference/apis/js-apis-screen.md#setorientation-1) |
-| [setShowOnLockScreen(show:boolean, callback:AsyncCallback<void>):void;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreen7) [setShowOnLockScreen(show:boolean):Promise<void>;](../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<void>):void;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreendeprecated) [setShowOnLockScreen(show:boolean):Promise<void>;](../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<void>):void;](../reference/apis/js-apis-inner-app-context.md#contextsetwakeupscreen7) [setWakeUpScreen(wakeUp:boolean):Promise<void>;](../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<ProcessInfo>):void;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessinfo7) [getProcessInfo():Promise<ProcessInfo>;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessinfo7-1) | \@ohos.app.ability.abilityManager.d.ts | [getAbilityRunningInfos(callback: AsyncCallback<Array<AbilityRunningInfo>>): void;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos) [getAbilityRunningInfos(): Promise<Array<AbilityRunningInfo>>;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos-1) |
| [getElementName(callback:AsyncCallback<ElementName>):void;](../reference/apis/js-apis-inner-app-context.md#contextgetelementname7) [getElementName():Promise<ElementName>;](../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) [abilityInfo.bundleName: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
@@ -26,5 +26,3 @@
| [getAbilityInfo(callback:AsyncCallback<AbilityInfo>):void;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7) [getAbilityInfo():Promise<AbilityInfo>;](../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<boolean>):void;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7) [isUpdatingConfigurations():Promise<boolean>;](../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<void>):void;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7) [printDrawnCompleted():Promise<void>;](../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 newline at end of file
diff --git a/en/application-dev/application-models/explicit-implicit-want-mappings.md b/en/application-dev/application-models/explicit-implicit-want-mappings.md
index 32482e090b41fa9497a8f385e2126e5b7152287b..15b7fd78a569258bdcc7697d716a38d717cf0d83 100644
--- a/en/application-dev/application-models/explicit-implicit-want-mappings.md
+++ b/en/application-dev/application-models/explicit-implicit-want-mappings.md
@@ -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<string> | 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: string]: any} | No| No| This field is not used for matching. It is passed to the target application component as a parameter.|
+| parameters | {[key: string]: 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<string> | 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: string]: any} | No | No | This field is not used for matching. It is passed to the target application component as a parameter. |
+| parameters | {[key: string]: 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:
diff --git a/en/application-dev/application-models/figures/component-startup-inner-stage.png b/en/application-dev/application-models/figures/component-startup-inner-stage.png
index 00514276f4ac3eb8ead650e5858cebb0a344d2c6..9761b9879e513f0e1ad942b5fe18997f1331c9e5 100644
Binary files a/en/application-dev/application-models/figures/component-startup-inner-stage.png and b/en/application-dev/application-models/figures/component-startup-inner-stage.png differ
diff --git a/en/application-dev/application-models/figures/component-startup-inter-stage.png b/en/application-dev/application-models/figures/component-startup-inter-stage.png
index a6f79e6803edc160e5570729456569f46cc80967..517407f6b557648db78a0de89431d8b18f8e2b59 100644
Binary files a/en/application-dev/application-models/figures/component-startup-inter-stage.png and b/en/application-dev/application-models/figures/component-startup-inter-stage.png differ
diff --git a/en/application-dev/application-models/hop-cross-device-migration.md b/en/application-dev/application-models/hop-cross-device-migration.md
index 92c254514d82cbcfe800f5b35bfefb96411a8f92..b452d8ea493bbfe060094f13073b9bdd9eac4f65 100644
--- a/en/application-dev/application-models/hop-cross-device-migration.md
+++ b/en/application-dev/application-models/hop-cross-device-migration.md
@@ -53,9 +53,9 @@ The table below describes the main APIs used for cross-device migration. For det
| **API**| Description|
| -------- | -------- |
-| onContinue(wantParam : {[key: string]: any}): OnContinueResult | Called by the initiator to store the data required for migration and indicate whether the migration is accepted. - **AGREE**: The migration is accepted. - **REJECT**: The migration is rejected, for example, when an application is abnormal in **onContinue()**. - **MISMATCH**: The version does not match. The application on the initiator can obtain the version number of the target application from **onContinue()**. If the migration cannot be performed due to version mismatch, this error code is returned.|
-| onCreate(want: Want, param: AbilityConstant.LaunchParam): void; | Called by the target to restore the data and UI page in the multiton migration scenario. For details, see [UIAbility Component Launch Type](uiability-launch-type.md).|
-| onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void; | Called by the target to restore the data and UI page in the singleton migration scenario. For details, see [UIAbility Component Launch Type](uiability-launch-type.md).|
+| onContinue(wantParam : {[key: string]: Object}): OnContinueResult | Called by the initiator to store the data required for migration and indicate whether the migration is accepted. - **AGREE**: The migration is accepted. - **REJECT**: The migration is rejected, for example, when an application is abnormal in **onContinue()**. - **MISMATCH**: The version does not match. The application on the initiator can obtain the version number of the target application from **onContinue()**. If the migration cannot be performed due to version mismatch, this error code is returned.|
+| onCreate(want: Want, param: AbilityConstant.LaunchParam): void; | Called by the target to restore the data and UI page when the target uses cold start or the target is a multiton application and uses hot start. For details, see [UIAbility Component Launch Type](uiability-launch-type.md).|
+| onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void; | Called by the target to restore the data and UI page when the target is a singleton application and uses hot start. For details, see [UIAbility Component Launch Type](uiability-launch-type.md).|
@@ -90,7 +90,7 @@ The table below describes the main APIs used for cross-device migration. For det
4. Implement [onContinue()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncontinue) in the UIAbility of the initiator.
- [onContinue()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncontinue) is called on the initiator. You can save the data in this method to implement application compatibility check and migration decision.
+ [onContinue()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncontinue) is called on the initiator. You can save the data in this method to implement application compatibility check and migration decision.
- Saving migrated data: You can save the data to be migrated in key-value pairs in **wantParam**.
- Checking application compatibility: You can obtain the version number of the target application from **wantParam** and that of the current application from **wantParam.version** of the **onContinue()** callback. Then you can check the compatibility between the two.
@@ -114,7 +114,7 @@ The table below describes the main APIs used for cross-device migration. For det
```
5. Implement **onCreate()** and **onNewWant()** in the UIAbility of the target application to implement data restoration.
- - Implementation example of **onCreate** in the multiton scenario
+ - Implementation example of **onCreate**
- The target device determines whether the startup is **LaunchReason.CONTINUATION** based on **launchReason** in **onCreate()**.
- You can obtain the saved migration data from the **want** parameter.
- After data restoration is complete, call **restoreWindowStage** to trigger page restoration, including page stack information.
@@ -139,11 +139,29 @@ The table below describes the main APIs used for cross-device migration. For det
}
}
```
- - For a singleton ability, use **onNewWant()** to achieve the same implementation.
+ - For a singleton application, you must also implement **onNewWant()**, in the same way as **onCreate()**.
+ - Determine the migration scenario in **onNewWant()**, restore data, and trigger page restoration.
+ ```ts
+ export default class EntryAbility extends UIAbility {
+ storage : LocalStorage;
+ onNewWant(want, launchParam) {
+ console.info(`EntryAbility onNewWant ${AbilityConstant.LaunchReason.CONTINUATION}`)
+ if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
+ // Obtain the user data from the want parameter.
+ let workInput = want.parameters.work
+ console.info(`work input ${workInput}`)
+ AppStorage.SetOrCreate('ContinueWork', workInput)
+ this.storage = new LocalStorage();
+ this.context.restoreWindowStage(this.storage);
+ }
+ }
+ }
+ ```
+
6. (Optional) Call [setMissionContinueState](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissioncontinuestate10) to set the mission continuation state.
- For an application that supports migration, mission migration is enabled by default, and the system notifies peripheral trusted devices that a mission can be migrated or canceled based on the gain/loss focus state of the mission. If you want the system to send a notification to peripheral devices only when your application is in a specific scenario, set the migration continuation state to **INACTIVE** when the application is started and change it to **ACTIVE** when the application enters that specific scenario. For details about the API, see [setMissionContinueState](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissioncontinuestate10).
+ For an application that supports migration, mission migration is enabled by default, and the system notifies peripheral trusted devices that a mission can be migrated or canceled based on the gain/loss focus state of the mission. If you want the system to send a notification to peripheral devices only when your application is in a specific scenario, set the migration continuation state to **INACTIVE** when the application is started and change it to **ACTIVE** when the application enters that specific scenario.
- Example: An application does not require migration during startup.
@@ -180,7 +198,7 @@ The table below describes the main APIs used for cross-device migration. For det
onContinue(wantParam : {[key: string]: any}) {
console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`)
- wantParam[wantConstant.SUPPORT_CONTINUE_PAGE_STACK_KEY] = false;
+ wantParam[wantConstant.Params.SUPPORT_CONTINUE_PAGE_STACK_KEY] = false;
return AbilityConstant.OnContinueResult.AGREE;
}
@@ -202,7 +220,7 @@ The table below describes the main APIs used for cross-device migration. For det
onContinue(wantParam : {[key: string]: any}) {
console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`)
- wantParam[wantConstant.SUPPORT_CONTINUE_SOURCE_EXIT_KEY] = false;
+ wantParam[wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY] = false;
return AbilityConstant.OnContinueResult.AGREE;
}
```
diff --git a/en/application-dev/application-models/lifecycleapp-switch.md b/en/application-dev/application-models/lifecycleapp-switch.md
index e2fa51264d4d41f52cef0a91e119a9e9d8e75d78..ae18625ecee0d281e9bd37b806bba5ae69a385c2 100644
--- a/en/application-dev/application-models/lifecycleapp-switch.md
+++ b/en/application-dev/application-models/lifecycleapp-switch.md
@@ -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) [onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) 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) 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) |
diff --git a/en/application-dev/application-models/lifecycleform-switch.md b/en/application-dev/application-models/lifecycleform-switch.md
index 6356d632e2dc20d5217bb32f2088061d9ab8fe8f..aee1059999aaca41b0c4b725201c6198d4fea209 100644
--- a/en/application-dev/application-models/lifecycleform-switch.md
+++ b/en/application-dev/application-models/lifecycleform-switch.md
@@ -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) |
diff --git a/en/application-dev/application-models/medialibrary-switch.md b/en/application-dev/application-models/medialibrary-switch.md
index dc671d1b61b467f98d7d01f43703b165df4c1e52..b5c8891f21fd2a554a2905f0f1cce59847e7f8ad 100644
--- a/en/application-dev/application-models/medialibrary-switch.md
+++ b/en/application-dev/application-models/medialibrary-switch.md
@@ -1,6 +1,6 @@
# mediaLibrary Switching
- | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model|
+| API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model|
| -------- | -------- | -------- |
-| [getMediaLibrary(): MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary) | \@ohos.multimedia.mediaLibrary.d.ts | [getMediaLibrary(context: Context): MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary8) |
+| [getMediaLibrary(): MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary) | \@ohos.file.photoAccessHelper.d.ts | [getPhotoAccessHelper(context: Context): PhotoAccessHelper;](../reference/apis/js-apis-photoAccessHelper.md#photoaccesshelpergetphotoaccesshelper) |
diff --git a/en/application-dev/application-models/particleability-switch.md b/en/application-dev/application-models/particleability-switch.md
index 7686ab281f8b6dd8b17e13fa0cbebd8cd6382d09..a5972c93f4c806f69ea80d6fa1d27dd344098bfd 100644
--- a/en/application-dev/application-models/particleability-switch.md
+++ b/en/application-dev/application-models/particleability-switch.md
@@ -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) [connectServiceExtensionAbility(want: Want, options: ConnectOptions): number;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextconnectserviceextensionability) |
| [disconnectAbility(connection: number, callback:AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitydisconnectability) [disconnectAbility(connection: number): Promise<void>;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitydisconnectability-1) | application\ServiceExtensionContext.d.ts | [disconnectAbility(connection: number, callback:AsyncCallback<void>): void; ](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability) [disconnectAbility(connection: number): Promise<void>;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability-1) [disconnectServiceExtensionAbility(connection: number, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability) [disconnectServiceExtensionAbility(connection: number): Promise<void>;](../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 [\@ohos.data.fileAccess.d.ts | [createDataShareHelper(context: Context, uri: string, callback: AsyncCallback<DataShareHelper>): void;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper) [createDataShareHelper(context: Context, uri: string): Promise<DataShareHelper>;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper-1) [createFileAccessHelper(context: Context): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper-1) [createFileAccessHelper(context: Context, wants: Array<Want>): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper) |
-| [startBackgroundRunning(id: number, request: NotificationRequest, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning) [startBackgroundRunning(id: number, request: NotificationRequest): Promise<void>;](../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) [startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent): Promise<void>;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningpromise) |
-| [cancelBackgroundRunning(callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning) [cancelBackgroundRunning(): Promise<void>;](../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) [stopBackgroundRunning(context: Context): Promise<void>;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningpromise) |
-
-
\ No newline at end of file
+| [startBackgroundRunning(id: number, request: NotificationRequest, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning) [startBackgroundRunning(id: number, request: NotificationRequest): Promise<void>;](../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) [startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent): Promise<void>;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunning-1) |
+| [cancelBackgroundRunning(callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning) [cancelBackgroundRunning(): Promise<void>;](../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) [stopBackgroundRunning(context: Context): Promise<void>;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunning-1) |
diff --git a/en/application-dev/application-models/start-pageability-from-stage.md b/en/application-dev/application-models/start-pageability-from-stage.md
index bd6a11187fdfbc81c63bcc6601f8a8e82b0dbe4c..123e15c45614f83ece1c11db87827535b2ac4937 100644
--- a/en/application-dev/application-models/start-pageability-from-stage.md
+++ b/en/application-dev/application-models/start-pageability-from-stage.md
@@ -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.');
diff --git a/en/application-dev/application-models/start-uiability-from-fa.md b/en/application-dev/application-models/start-uiability-from-fa.md
index 42d8e034cd6519643423bb289217d1aa140a18d4..8520cf94be0d0d21999af3175848a37edac85c52 100644
--- a/en/application-dev/application-models/start-uiability-from-fa.md
+++ b/en/application-dev/application-models/start-uiability-from-fa.md
@@ -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) => {
diff --git a/en/application-dev/application-models/uiability-intra-device-interaction.md b/en/application-dev/application-models/uiability-intra-device-interaction.md
index 2ed36f466408f4280ef516f405bc0e6837fb31f6..56dd9198f291352413f72e3b2ada766c5c729e38 100644
--- a/en/application-dev/application-models/uiability-intra-device-interaction.md
+++ b/en/application-dev/application-models/uiability-intra-device-interaction.md
@@ -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.
+

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.

@@ -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.
+```
-
+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() {
- ...
- }
+ ...
}
```
diff --git a/en/application-dev/application-models/uiability-launch-type.md b/en/application-dev/application-models/uiability-launch-type.md
index 3b91469c1db08e2cbed59c7fceb4563547b54a72..03ae09de4f54a956506881e20a4bf45ec3bb8fe4 100644
--- a/en/application-dev/application-models/uiability-launch-type.md
+++ b/en/application-dev/application-models/uiability-launch-type.md
@@ -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.
diff --git a/en/application-dev/application-models/want-overview.md b/en/application-dev/application-models/want-overview.md
index cf5cac43999a5efbe59659252b6b3db325cacd8a..9260c71666f3c47181756ba205c265391d989b05 100644
--- a/en/application-dev/application-models/want-overview.md
+++ b/en/application-dev/application-models/want-overview.md
@@ -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.
diff --git a/en/application-dev/application-models/widget-development-fa.md b/en/application-dev/application-models/widget-development-fa.md
index 5405cf30050269a97039bc2e9d898da7b5ee1dc8..7061ad6db08cca845f478c9a18685d2301cdafbe 100644
--- a/en/application-dev/application-models/widget-development-fa.md
+++ b/en/application-dev/application-models/widget-development-fa.md
@@ -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?: Object \| string): 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.
diff --git a/en/application-dev/arkts-utils/Readme-EN.md b/en/application-dev/arkts-utils/Readme-EN.md
new file mode 100644
index 0000000000000000000000000000000000000000..a574b494aea8d5bc7b62a000044fa81ae269b43e
--- /dev/null
+++ b/en/application-dev/arkts-utils/Readme-EN.md
@@ -0,0 +1,23 @@
+# ArkTS Common Library
+
+- [Overview of ArkTS Common Library](arkts-commonlibrary-overview.md)
+- Concurrency
+ - [Concurrency Overview](concurrency-overview.md)
+ - Using Asynchronous Concurrency for Development
+ - [Asynchronous Concurrency Overview](async-concurrency-overview.md)
+ - [Single I/O Task Development](single-io-development.md)
+ - Using Multithread Concurrency for Development
+ - [Multithread Concurrency Overview](multi-thread-concurrency-overview.md)
+ - [Comparison Between TaskPool and Worker](taskpool-vs-worker.md)
+ - [CPU Intensive Task Development](cpu-intensive-task-development.md)
+ - [I/O Intensive Task Development](io-intensive-task-development.md)
+ - [Synchronous Task Development](sync-task-development.md)
+- Container
+ - [Container Overview](container-overview.md)
+ - [Linear Containers](linear-container.md)
+ - [Nonlinear Containers](nonlinear-container.md)
+- XML Generation, Parsing, and Conversion
+ - [XML Overview](xml-overview.md)
+ - [XML Generation](xml-generation.md)
+ - [XML Parsing](xml-parsing.md)
+ - [XML Conversion](xml-conversion.md)
diff --git a/en/application-dev/arkts-utils/arkts-commonlibrary-overview.md b/en/application-dev/arkts-utils/arkts-commonlibrary-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..708f14c78da7c7bd53d66cd62826ff01c5d6e212
--- /dev/null
+++ b/en/application-dev/arkts-utils/arkts-commonlibrary-overview.md
@@ -0,0 +1,31 @@
+# Overview of ArkTS Common Library
+
+
+The ArkTS common library provides common basic capabilities, as illustrated in the figure below.
+
+
+**Figure 1** Capabilities of the ArkTS common library
+
+
+
+
+- Supporting [asynchronous concurrency and multithread concurrency](concurrency-overview.md)
+ - Supports standard JavaScript asynchronous concurrency capabilities such as Promise and async/await.
+ - Uses **TaskPool** to provide a multithread running environment for applications. The use of **TaskPool** helps reduce resource consumption and improve system performance. It also frees you from caring about the lifecycle of thread instances.
+ - Uses **Worker** to support multithread concurrency. The worker thread can communicate with the host thread. You need to proactively create and close a worker thread.
+
+- Providing common capabilities of [adding, deleting, modifying, and querying elements in containers](container-overview.md)
+
+- Constructing and parsing XML files, URLs, and URIs
+ - Extensible Markup Language (XML) is designed for data transmission and storage. The common library provides APIs for [XML generation, parsing, and conversion](xml-overview.md).
+ - [URI](../reference/apis/js-apis-uri.md) is a uniform resource identifier that uniquely identifies a resource. [URL](../reference/apis/js-apis-url.md) is a uniform resource locator that provides a path for locating a resource.
+
+- Supporting common [string and binary data processing](../reference/apis/js-apis-util.md) and [logging](../reference/apis/js-apis-logs.md)
+ - Provides APIs to encode and decode strings.
+ - Provides APIs to encode and decode Base64-encoded bytes.
+ - Supports common rational number operations, including comparing rational numbers and obtaining numerators and denominators.
+ - Provides **Scope** APIs to define the valid range of a field.
+ - Provides APIs to process binary data in scenarios such as TCP flows or file system operations.
+ - Supports logging using the console.
+
+- Providing the capability of [obtaining process information and operating processes](../reference/apis/js-apis-process.md)
\ No newline at end of file
diff --git a/en/application-dev/arkts-utils/async-concurrency-overview.md b/en/application-dev/arkts-utils/async-concurrency-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..32bed2f143b9dbf32369fb439290d762269e055a
--- /dev/null
+++ b/en/application-dev/arkts-utils/async-concurrency-overview.md
@@ -0,0 +1,87 @@
+# Asynchronous Concurrency Overview
+
+
+Promise and async/await are standard JavaScript syntax that provides asynchronous concurrency. Asynchronous code ensures that actions initiated now finish later. It allows the execution of only one segment of code at a time and is therefore applicable to the development of a single I/O task, for example, a network request or a file read/write operation.
+
+
+Promise and async/await allow an application to perform other operations without waiting for the completion of certain actions.
+
+
+## Promise
+
+Promise is an object used to process asynchronous operations. It converts asynchronous operations into a style similar to synchronous operations for easier code writing and maintenance. Promise provides a state mechanism to manage different phases of asynchronous operations. It also provides methods to register callback functions to handle the success or failure of these operations.
+
+Promise has three states: pending, fulfilled, and rejected. After being created, a Promise object is in the pending state and changes to the fulfilled or rejected state when the asynchronous operation is complete.
+
+The most common usage for Promise is to instantiate a Promise object through a constructor and pass in a function (usually named **executor**) with two parameters. The **executor** function receives two parameters: **resolve** and **reject**, which represent the callback functions that should be called when the asynchronous operation succeeds and fails, respectively. The code snippet below creates a Promise object and simulates an asynchronous operation:
+
+
+```js
+const promise = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const randomNumber = Math.random();
+ if (randomNumber > 0.5) {
+ resolve(randomNumber);
+ } else {
+ reject(new Error('Random number is too small'));
+ }
+ }, 1000);
+});
+```
+
+In the preceding code, the **setTimeout** function simulates an asynchronous operation that randomly generates a number one second later. If the random number is greater than 0.5, the **resolve** callback function is executed and the generated random number is passed in as a parameter. Otherwise, the **reject** callback function is executed and an error object is passed in as a parameter.
+
+After the Promise object is created, you can use the **then** and **catch** methods to register the callback functions for the fulfilled and rejected states. The **then** method can receive two parameters: one for processing the fulfilled state and the other for processing the rejected state. If only one parameter is passed in, the callback function is executed as long as the state changes. The **catch** method receives a callback function to process the failure result, that is, capture the exception thrown when the Promise state changes to **rejected** or the operation fails. The code snippet below shows the use of **then** and **catch** methods:
+
+
+```js
+promise.then(result => {
+ console.info(`Random number is ${result}`);
+}).catch(error => {
+ console.error(error.message);
+});
+```
+
+In the preceding code, the callback function of the **then** method receives the success result of the Promise object as a parameter and outputs it to the console. If the Promise object enters the rejected state, the callback function of the **catch** method receives the error object as a parameter and outputs it to the console.
+
+
+## Async/Await
+
+Async/Await is a Promise syntax sugar used to process asynchronous operations, making it easier to read and write asynchronous code. The async keyword is used to declare an asynchronous function, and the await keyword is used to wait for Promise parsing (fulfilled or rejected). In this way, the asynchronous operation logic is coded as a synchronous operation.
+
+The **async** function returns a Promise object to represent an asynchronous operation. Inside the **async** function, you can use the await keyword to wait for the parsing of the Promise object and return its parsed value. If an **async** function throws an exception, the Promise object returned by the function is rejected, and the exception information is passed to the **onRejected()** method of the Promise object.
+
+The code snippet below uses async/await to simulate an asynchronous operation that returns a string three seconds later.
+
+
+```js
+async function myAsyncFunction() {
+ const result = await new Promise((resolve) => {
+ setTimeout(() => {
+ resolve('Hello, world!');
+ }, 3000);
+ });
+ console.info(String(result)); // Output: Hello, world!
+}
+
+myAsyncFunction();
+```
+
+In the preceding code, the await keyword is used to wait for the parsing of the Promise object and store its parsed value in the **result** variable.
+
+Note that the entire operation must be packaged in the **async** function because the code needs to wait for the asynchronous operation to complete. In addition to **await**, you can use the try/catch block to capture exceptions in asynchronous operations.
+
+
+```js
+async function myAsyncFunction() {
+ try {
+ const result = await new Promise((resolve) => {
+ resolve('Hello, world!');
+ });
+ } catch (e) {
+ console.error(`Get exception: ${e}`);
+ }
+}
+
+myAsyncFunction();
+```
diff --git a/en/application-dev/arkts-utils/concurrency-overview.md b/en/application-dev/arkts-utils/concurrency-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..3f091f42ea1257468aba5ba9ed94e64c92f661bb
--- /dev/null
+++ b/en/application-dev/arkts-utils/concurrency-overview.md
@@ -0,0 +1,15 @@
+# Concurrency Overview
+
+Concurrency refers to the capability of processing multiple tasks in the same period. To improve the response speed and frame rate of applications and prevent time-consuming tasks from blocking the main thread, OpenHarmony provides two policies: asynchronous concurrency and multithread concurrency.
+
+- Asynchronous concurrency means that an action in asynchronous code is suspended and will continue later. Only one segment of code is being executed at a time.
+
+- Multithread concurrency allows multiple segments of code to be executed at a time. When the main thread continues to respond to user operations and update the UI, time-consuming operations are performed in the background to avoid application freezing.
+
+Concurrency is used in a variety of scenarios, including a single I/O task, CPU intensive task, I/O intensive task, synchronous task, and the like. You can select a concurrency policy based on your scenario.
+
+ArkTS provides the following mechanisms to support asynchronous concurrency and multithread concurrency:
+
+- Promise and async/await: provide asynchronous concurrency and apply to the development of a single I/O task. For details, see [Asynchronous Concurrency Overview](async-concurrency-overview.md).
+
+- **TaskPool** and **Worker**: provide multithread concurrency and apply to the development of CPU intensive tasks, I/O intensive tasks, and synchronous tasks. For details, see [Multithread Concurrency Overview](multi-thread-concurrency-overview.md).
diff --git a/en/application-dev/arkts-utils/container-overview.md b/en/application-dev/arkts-utils/container-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..8a317e23167644ad72287c05672c3aa4a641cd29
--- /dev/null
+++ b/en/application-dev/arkts-utils/container-overview.md
@@ -0,0 +1,7 @@
+# Overview of Containers
+
+The container classes provide a set of methods to process elements of various data types stored in containers.
+
+The container classes are implemented in a way similar to static languages. By restricting storage locations and attributes, they remove redundant logic for each type of data while providing the complete functionalities, ensuring efficient data access and improving application performance.
+
+Currently, OpenHarmony provides 14 types of linear and non-linear containers, each of which has its own features and uses cases. For details, see [Linear Containers](linear-container.md) and [Nonlinear Containers](nonlinear-container.md).
diff --git a/en/application-dev/arkts-utils/cpu-intensive-task-development.md b/en/application-dev/arkts-utils/cpu-intensive-task-development.md
new file mode 100644
index 0000000000000000000000000000000000000000..da11a1866dbeb1d374972fde6579676387d97ada
--- /dev/null
+++ b/en/application-dev/arkts-utils/cpu-intensive-task-development.md
@@ -0,0 +1,190 @@
+# CPU Intensive Task Development
+
+
+CPU intensive tasks occupy lots of system computing resources for a long period of time, during which other events of the thread are blocked. Example CPU intensive tasks are image processing, video encoding, and data analysis.
+
+
+OpenHarmony uses multithread concurrency to process CPU intensive tasks. This improves CPU utilization and application response speed.
+
+
+If a task does not need to occupy a background thread for a long time (3 minutes), you are advised to use **TaskPool**. Otherwise, use **Worker**. The following uses histogram processing and a time-consuming model prediction task in the background as examples.
+
+
+## Using TaskPool to Process Histograms
+
+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.
+
+
+```ts
+import taskpool from '@ohos.taskpool';
+
+@Concurrent
+function imageProcessing(dataSlice: ArrayBuffer) {
+ // Step 1: Perform specific image processing operations and other time-consuming operations.
+ return dataSlice;
+}
+
+function histogramStatistic(pixelBuffer: ArrayBuffer) {
+ // Step 2: Perform concurrent scheduling for data in three segments.
+ let number = pixelBuffer.byteLength / 3;
+ let buffer1 = pixelBuffer.slice(0, number);
+ let buffer2 = pixelBuffer.slice(number, number * 2);
+ let buffer3 = pixelBuffer.slice(number * 2);
+
+ let group = new taskpool.TaskGroup();
+ group.addTask(imageProcessing, buffer1);
+ group.addTask(imageProcessing, buffer2);
+ group.addTask(imageProcessing, buffer3);
+
+ taskpool.execute(group, taskpool.Priority.HIGH).then((ret: ArrayBuffer[]) => {
+ // Step 3: Summarize and process the result arrays.
+ })
+}
+
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World'
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ .onClick(() => {
+ let data: ArrayBuffer;
+ histogramStatistic(data);
+ })
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
+```
+
+
+## Using Worker for Time-Consuming Data Analysis
+
+The following uses the training of a region-specific house price prediction model as an example. This model can be used to predict house prices in the region based on the house area and number of rooms. The model needs to run for a long time, and the prediction will use the previous running result. Due to these considerations, **Worker** is used for the development.
+
+1. Add the worker creation template provided on DevEco Studio to your project, and name it **MyWorker**.
+
+ 
+
+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';
+
+ const workerInstance = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
+ ```
+
+3. In the host thread, call [onmessage()](../reference/apis/js-apis-worker.md#onmessage9) to receive messages from the worker thread, and call [postMessage()](../reference/apis/js-apis-worker.md#postmessage9) to send messages to the worker thread.
+
+ For example, the host thread sends training and prediction messages to the worker thread, and receives messages sent back by the worker thread.
+
+
+ ```js
+ // Receive the result of the worker thread.
+ workerInstance.onmessage = function(e) {
+ // data carries the information sent by the main thread.
+ let data = e.data;
+ console.info('MyWorker.ts onmessage');
+ // Perform time-consuming operations in the worker thread.
+ }
+
+ workerInstance.onerror = function (d) {
+ // Receive error information of the worker thread.
+ }
+
+ // Send a training message to the worker thread.
+ workerInstance.postMessage({ 'type': 0 });
+ // Send a prediction message to the worker thread.
+ workerInstance.postMessage({ 'type': 1, 'value': [90, 5] });
+ ```
+
+4. Bind the **Worker** object in the **MyWorker.ts** file. The calling thread is the worker thread.
+
+ ```js
+ import worker, { ThreadWorkerGlobalScope, MessageEvents, ErrorEvent } from '@ohos.worker';
+
+ let workerPort: ThreadWorkerGlobalScope = worker.workerPort;
+ ```
+
+5. In the worker thread, call [onmessage()](../reference/apis/js-apis-worker.md#onmessage9-1) to receive messages sent by the host thread, and call [postMessage()](../reference/apis/js-apis-worker.md#postmessage9-2) to send messages to the host thread.
+
+ For example, the prediction model and its training process are defined in the worker thread, and messages are exchanged with the main thread.
+
+
+ ```js
+ import worker, { ThreadWorkerGlobalScope, MessageEvents, ErrorEvent } from '@ohos.worker';
+
+ let workerPort: ThreadWorkerGlobalScope = worker.workerPort;
+
+ // Define the training model and result.
+ let result;
+
+ // Define the prediction function.
+ function predict(x) {
+ return result[x];
+ }
+
+ // Define the optimizer training process.
+ function optimize() {
+ result = {};
+ }
+
+ // onmessage logic of the worker thread.
+ workerPort.onmessage = function (e: MessageEvents) {
+ let data = e.data
+ // Perform operations based on the type of data to transmit.
+ switch (data.type) {
+ case 0:
+ // Perform training.
+ optimize();
+ // Send a training success message to the main thread after training is complete.
+ workerPort.postMessage({ type: 'message', value: 'train success.' });
+ break;
+ case 1:
+ // Execute the prediction.
+ const output = predict(data.value);
+ // Send the prediction result to the main thread.
+ workerPort.postMessage({ type: 'predict', value: output });
+ break;
+ default:
+ workerPort.postMessage({ type: 'message', value: 'send message is invalid' });
+ break;
+ }
+ }
+ ```
+
+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");
+ }
+ ```
+
+ 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.
+ workerInstance.terminate();
+ ```
+
+ 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();
+ ```
diff --git a/en/application-dev/arkts-utils/figures/arkts-commonlibrary.png b/en/application-dev/arkts-utils/figures/arkts-commonlibrary.png
new file mode 100644
index 0000000000000000000000000000000000000000..e8590f0115429b7857e3d7d44b7dceb821857515
Binary files /dev/null and b/en/application-dev/arkts-utils/figures/arkts-commonlibrary.png differ
diff --git a/en/application-dev/arkts-utils/figures/newWorker.png b/en/application-dev/arkts-utils/figures/newWorker.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1b47bb4a885cf793ed467db43151a99720ea48d
Binary files /dev/null and b/en/application-dev/arkts-utils/figures/newWorker.png differ
diff --git a/en/application-dev/arkts-utils/figures/taskpool.png b/en/application-dev/arkts-utils/figures/taskpool.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5ae190d4dece65d196fd635b08ae6b420b6033b
Binary files /dev/null and b/en/application-dev/arkts-utils/figures/taskpool.png differ
diff --git a/en/application-dev/arkts-utils/figures/worker.png b/en/application-dev/arkts-utils/figures/worker.png
new file mode 100644
index 0000000000000000000000000000000000000000..5feb2f6e5a01e4686a3cb3fe2451d72ae80c8685
Binary files /dev/null and b/en/application-dev/arkts-utils/figures/worker.png differ
diff --git a/en/application-dev/arkts-utils/io-intensive-task-development.md b/en/application-dev/arkts-utils/io-intensive-task-development.md
new file mode 100644
index 0000000000000000000000000000000000000000..562f749fd99daff42359af2598bc42483dc5595c
--- /dev/null
+++ b/en/application-dev/arkts-utils/io-intensive-task-development.md
@@ -0,0 +1,51 @@
+# I/O Intensive Task Development
+
+
+Asynchronous concurrency can solve the problem of a single blocking I/O operation. In the case of I/O intensive tasks, the execution of other tasks in the thread is still blocked. To resolve this issue, multithread concurrency is introduced.
+
+
+The performance focus of I/O intensive tasks is not the CPU processing capability, but the speed and efficiency of I/O operations, since such a task usually requires frequent operations such as disk read/write and network communication. The following uses frequent read/write operations on a system file to simulate concurrency processing of I/O intensive tasks.
+
+
+1. Define a concurrency function that internally calls I/O capabilities intensively.
+
+ ```ts
+ import fs from '@ohos.file.fs';
+
+ // Define a concurrency function that internally calls I/O capabilities intensively.
+ @Concurrent
+ async function concurrentTest(fileList: string[]) {
+ // Implement file writing.
+ async function write(data, filePath) {
+ let file = await fs.open(filePath, fs.OpenMode.READ_WRITE);
+ await fs.write(file.fd, data);
+ fs.close(file);
+ }
+ // Write the file cyclically.
+ for (let i = 0; i < fileList.length; i++) {
+ write('Hello World!', fileList[i]).then(() => {
+ console.info(`Succeeded in writing the file. FileList: ${fileList[i]}`);
+ }).catch((err) => {
+ console.error(`Failed to write the file. Code is ${err.code}, message is ${err.message}`)
+ return false;
+ })
+ }
+ return true;
+ }
+ ```
+
+2. Use **TaskPool** to execute the concurrency function that contains the intensive I/O operations. Specifically, call [execute()](../reference/apis/js-apis-taskpool.md#taskpoolexecute) to execute the tasks and process the scheduling result in a callback. For details about how to obtain **filePath1** and **filePath2** in the example, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths).
+
+ ```ts
+ import taskpool from '@ohos.taskpool';
+
+ let filePath1 =...; // Application file path
+ let filePath2 = ...;
+
+ // Use TaskPool to execute the concurrency function that contains the intensive I/O operations.
+ // In the case of a large array, the distribution of I/O intensive tasks also preempts the main thread. Therefore, multiple threads are required.
+ taskpool.execute(concurrentTest, [filePath1, filePath2]).then((ret) => {
+ // Process the scheduling result.
+ console.info(`The result: ${ret}`);
+ })
+ ```
diff --git a/en/application-dev/arkts-utils/linear-container.md b/en/application-dev/arkts-utils/linear-container.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed8ab890864a7d525aa24c096431b12d3d18e5
--- /dev/null
+++ b/en/application-dev/arkts-utils/linear-container.md
@@ -0,0 +1,253 @@
+# Linear Containers
+
+
+Linear containers implement a data structure that enables sequential access. The bottom layer of linear containers is implemented through arrays. OpenHarmony provides the following linear containers: **ArrayList**, **Vector**, **List**, **LinkedList**, **Deque**, **Queue**, and **Stack**.
+
+
+Fully considering the data access speed, linear containers support Create, Read, Update, and Delete (CRUD) through a bytecode instruction at runtime.
+
+
+## ArrayList
+
+[ArrayList](../reference/apis/js-apis-arraylist.md) is a dynamic array that can be used to construct a global array object. You are advised to use **ArrayList** when elements in a container need to be frequently read.
+
+**ArrayList** uses generics and must be stored in a contiguous memory space. Its initial capacity is 10, and it increases capacity 1.5-fold in each dynamic expansion.
+
+**ArrayList** provides the following CRUD APIs.
+
+| Operation| Description|
+| --------- | ------- |
+| Adding elements| Use **add(element: T)** to add an element at the end of this container.|
+| Adding elements| Use **insert(element: T, index: number)** to insert an element at a given position (specified by **index**).|
+| Accessing elements| Use **arr\[index]** to obtain the value at a given position (specified by **index**).|
+| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, arrlist?: ArrayList<T>) => void, thisArg?: Object): void** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Modifying elements| Use **arr\[index] = xxx** to change 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.|
+
+
+## Vector
+
+[Vector](../reference/apis/js-apis-vector.md) is a continuous storage structure that can be used to construct a global array object. **Vector** uses generics and must be stored in a contiguous memory space. Its initial capacity is 10, and it has capacity doubled in each dynamic expansion.
+
+Both **Vector** and [ArrayList](../reference/apis/js-apis-arraylist.md) are implemented based on arrays, but **Vector** provides more interfaces for operating the arrays. In addition to operator access, **Vector** provides the getter and setter to provide a more complete verification and error tolerance mechanism.
+
+The APIs provided by **Vector** are deprecated since API version 9. You are advised to use [ArrayList](../reference/apis/js-apis-arraylist.md).
+
+**Vector** provides the following CRUD APIs.
+
+| Operation| Description|
+| --------- | ------- |
+| Adding elements| Use **add(element: T)** to add an element at the end of this container.|
+| Adding elements| Use **insert(element: T, index: number)** to insert an element at a given position (specified by **index**).|
+| 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 **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<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** 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 **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.|
+
+
+## List
+
+[List](../reference/apis/js-apis-list.md) can be used to construct a singly linked list, which supports access only through the head node to the tail node. **List** uses generics and can be stored in a non-contiguous memory space.
+
+Unlike [LinkedList](../reference/apis/js-apis-linkedlist.md), which is a doubly linked list, **List** is a singly linked list that does not support insertion or removal at both ends.
+
+You are advised to use **List** for frequent insertion and removal operations.
+
+**List** provides the following CRUD APIs.
+
+| Operation| Description|
+| --------- | ------ |
+| Adding elements| Use **add(element: T)** to add an element at the end of this container.|
+| Adding elements| Use **insert(element: T, index: number)** to insert an element at a given position (specified by **index**).|
+| Accessing elements| Use **list\[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 **getFirst()** to obtain the first element in this container.|
+| Accessing elements| Use **getLast()** to obtain the last element in this container.|
+| 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<T>)=> void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** 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<T>)=>T,thisArg?: Object)** to replace all elements in this container with new elements.|
+| 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.|
+
+
+## LinkedList
+
+[LinkedList](../reference/apis/js-apis-linkedlist.md) can be used to construct a doubly linked list, which can be traversed at both ends. **LinkedList** uses generics and can be stored in a non-contiguous memory space.
+
+Unlike [List](../reference/apis/js-apis-list.md), which is a singly linked list, **LinkedList** is a doubly linked list that supports insertion and removal at both ends.
+
+**LinkedList** is more efficient in data insertion than [ArrayList](../reference/apis/js-apis-arraylist.md), but less efficient in data access.
+
+You are advised to use **LinkedList** for frequent insertion and removal operations.
+
+**LinkedList** provides the following CRUD APIs.
+
+| Operation| Description|
+| ---------- | ------ |
+| Adding elements| Use **add(element: T)** to add an element at the end of this container.|
+| Adding elements| Use **insert(index: number, element: T)** to insert an element at a given position (specified by **index**).|
+| Accessing elements| Use **list\[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 **getFirst()** to obtain the first element in this container.|
+| Accessing elements| Use **getLast()** to obtain the last element in this container.|
+| 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<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** 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 **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.|
+
+
+## Deque
+
+[Deque](../reference/apis/js-apis-deque.md) can be used to construct a double-ended queue (deque) that follows the principles of First In First Out (FIFO) and Last In First Out (LIFO). It allows insertion and removal of elements at both the ends.
+
+**Deque** uses generics and must be stored in a contiguous memory space. Its initial capacity is 8, and it has capacity doubled in each dynamic expansion. The bottom layer of **Deque** is implemented by cyclic queues, delivering a high efficiency in enqueuing and dequeuing.
+
+[Queue](../reference/apis/js-apis-queue.md) follows the principle of FIFO only and allows element removal at the front and insertion at the rear.
+
+[Vector](../reference/apis/js-apis-vector.md) supports insertion and deletion of elements in between, as well as at both the ends. When compared with **Vector**, **Deque** is more efficient in inserting and removing header elements, but less efficient in accessing elements.
+
+You are advised to use **Deque** when you need to frequently insert or remove elements at both the ends of a container.
+
+**Deque** provides the following CRUD APIs.
+
+| Operation| Description|
+| ---------- | ------ |
+| Adding elements| Use **insertFront(element: T)** to insert an element at the front of this container.|
+| Adding elements| Use **insertEnd(element: T)** to insert an element at the end of this container.|
+| Accessing elements| Use **getFirst()** to obtain the value of the first element in this container, without removing it from the container.|
+| Accessing elements| Use **getLast()** to obtain the value of the last element in this container, without removing it from the container.|
+| Accessing elements| Use **popFirst()** to obtain the value of the first element in this container and remove it from the container.|
+| Accessing elements| Use **popLast()** to obtain the value of the last element in this container and remove it from the container.|
+| Accessing elements| Use **forEach(callbackFn:(value: T, index?: number, deque?: Deque<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Modifying elements| Use **forEach(callbackFn:(value: T, index?: number, deque?: Deque<T>)=> void, thisArg?: Object)** to modify an element in this container.|
+| Deleting elements| Use **popFirst()** to remove the first element from this container.|
+| Deleting elements| Use **popLast()** to remove the last element from this container.|
+
+
+## Queue
+
+[Queue](../reference/apis/js-apis-queue.md) can be used to construct a queue that follows the FIFO principle.
+
+**Queue** uses generics and must be stored in a contiguous memory space. Its initial capacity is 8, and it has capacity doubled in each dynamic expansion.
+
+The bottom layer of **Queue** is implemented by cyclic queues, delivering a high efficiency in enqueuing and dequeuing.
+
+Unlike [Deque](../reference/apis/js-apis-deque.md), which supports insertion and removal at both the ends, **Queue** supports insertion at one end and removal at the other end.
+
+You are advised to use **Queue** in FIFO scenarios.
+
+**Queue** provides the following CRUD APIs.
+
+| Operation| Description|
+| ---------- | ------ |
+| Adding elements| Use **add(element: T)** to add an element at the end of this container.|
+| Accessing elements| Use **getFirst()** to obtain the value of the first element in this container, without removing it from the container.|
+| Accessing elements| Use **pop()** to obtain the value of the first element in this container and remove it from the container.|
+| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, queue?: Queue<T>) => void,thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Modifying elements| Use **forEach(callbackFn:(value: T, index?: number, queue?: Queue<T>) => void,thisArg?: Object)** to modify an element in this container.|
+| Deleting elements| Use **pop()** to remove the first element from this container.|
+
+
+## Stack
+
+[Stack](../reference/apis/js-apis-stack.md) can be used to construct a stack that follows the Last Out First In (LOFI) principle.
+
+**Stack** uses generics and must be stored in a contiguous memory space. Its initial capacity is 8, and it increases capacity 1.5-fold in each dynamic expansion. The bottom layer of **Stack** is implemented based on arrays. It supports data insertion and removal at one end.
+
+Unlike [Queue](../reference/apis/js-apis-queue.md), which is implemented based on the queue data structure and supports insertion at one end and removal at the other end, **Stack** supports insertion and removal at the same end.
+
+You are advised to use **Stack** in LOFI scenarios.
+
+**Stack** provides the following CRUD APIs.
+
+| Operation| Description|
+| ---------- | ------ |
+| Adding elements| Use **push(item: T)** to add an element at the top of this container.|
+| Accessing elements| Use **peek()** to obtain the value of the top element in this container, without removing it from the container.|
+| Accessing elements| Use **pop()** to obtain the value of the top element in this container and remove it from the container.|
+| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, stack?: Stack<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Accessing elements| Use **locate(element: T)** to obtain the index of the first occurrence of the specified element.|
+| Modifying elements| Use **forEach(callbackFn:(value: T, index?: number, stack?: Stack<T>) => void, thisArg?: Object)** to modify an element in this container.|
+| Deleting elements| Use **pop()** to remove the top element from this container.|
+
+
+## Use of Linear Containers
+
+Refer to the code snippet below to add, access, and modify elements in **ArrayList**, **Vector**, **Deque**, **Stack**, and **List**.
+
+
+```js
+// ArrayList
+import ArrayList from '@ohos.util.ArrayList'; // Import the ArrayList module.
+
+let arrayList = new ArrayList();
+arrayList.add('a');
+arrayList.add(1); // Add an element.
+console.info(`result: ${arrayList[0]}`); // Access an element.
+arrayList[0] = 'one'; // Modify an element.
+console.info(`result: ${arrayList[0]}`);
+
+// Vector
+import Vector from '@ohos.util.Vector'; // Import the Vector module.
+
+let vector = new Vector();
+vector.add('a');
+let b1 = [1, 2, 3];
+vector.add(b1);
+vector.add(false); // Add an element.
+console.info(`result: ${vector[0]}`); // Access an element.
+console.info(`result: ${vector.getFirstElement()}`); // Access an element.
+
+// Deque
+import Deque from '@ohos.util.Deque'; // Import the Deque module.
+
+let deque = new Deque;
+deque.insertFront('a');
+deque.insertFront(1); // Add an element.
+console.info(`result: ${deque[0]}`); // Access an element.
+deque[0] = 'one'; // Modify an element.
+console.info(`result: ${deque[0]}`);
+
+// Stack
+import Stack from '@ohos.util.Stack'; // Import the Stack module.
+
+let stack = new Stack();
+stack.push('a');
+stack.push(1); // Add an element.
+console.info(`result: ${stack[0]}`); // Access an element.
+stack.pop(); // Remove an element.
+console.info(`result: ${stack.length}`);
+
+// List
+import List from '@ohos.util.List'; // Import the List module.
+
+let list = new List;
+list.add('a');
+list.add(1);
+let b2 = [1, 2, 3];
+list.add(b2); // Add an element.
+console.info(`result: ${list[0]}`); // Access an element.
+console.info(`result: ${list.get(0)}`); // Access an element.
+```
diff --git a/en/application-dev/arkts-utils/multi-thread-concurrency-overview.md b/en/application-dev/arkts-utils/multi-thread-concurrency-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..08451191025d01ecfcd3b70f8fb8170826c35dc4
--- /dev/null
+++ b/en/application-dev/arkts-utils/multi-thread-concurrency-overview.md
@@ -0,0 +1,62 @@
+# Multithread Concurrency Overview
+
+
+## Overview
+
+Concurrency models are used to implement concurrent tasks in different scenarios. Common concurrency models are classified into shared memory models and message passing models.
+
+A typical message passing model is actor. It provides a relatively high degree of concurrency while eliminating a series of complex and occasional issues caused by locks. For these reasons, ArkTS chooses the actor model.
+
+Due to the memory isolation feature of the actor model, cross-thread serialization is required.
+
+
+## Data Transfer 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
+
+The structured clone algorithm is used for serialization of common objects. This algorithm recursively transfers an object by clone. It supports more object types than other serialization algorithms.
+
+The following object types are supported: basic types except Symbol, Date, String, RegExp, Array, Map, Set, Object (simple objects only, for example, objects created using **{}** or **new Object**), ArrayBuffer, and typedArray. (Note that only attributes can be transferred for common objects. Prototypes and methods cannot be transferred.)
+
+
+### Transferable Objects
+
+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
+// Define a transferable object.
+let buffer = new ArrayBuffer(100);
+```
+
+
+### Shared Objects
+
+A shared object is of the **SharedArrayBuffer** type, has a fixed length, and can store any type of data including numbers and strings.
+
+An object of the SharedArrayBuffer type can be transferred between multiple threads. The objects before and after the transfer point to the same memory block, achieving memory sharing.
+
+If multiple operations are simultaneously performed to modify data stored in an object of the SharedArrayBuffer type, you must use atomics to ensure data synchronization. Atomics ensure that the current operation is complete before the next operation starts.
+
+
+```js
+// Define a shared object, which uses atomics to ensure data synchronization.
+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
+
+ArkTS provides two multithread concurrency capabilities: **TaskPool** and **Worker**, which differ in their implementation features and use cases. For details, see [Comparison Between TaskPool and Worker](taskpool-vs-worker.md).
diff --git a/en/application-dev/arkts-utils/nonlinear-container.md b/en/application-dev/arkts-utils/nonlinear-container.md
new file mode 100644
index 0000000000000000000000000000000000000000..b5c6380ae873b9dc47b69a6754b357f7dac8c1c8
--- /dev/null
+++ b/en/application-dev/arkts-utils/nonlinear-container.md
@@ -0,0 +1,253 @@
+# Nonlinear Containers
+
+
+Nonlinear containers implement a data structure that enables quick search. The bottom layer of nonlinear containers is implemented through hash tables or red-black trees. OpenHarmony provides the following nonlinear containers: **HashMap**, **HashSet**, **TreeMap**, **TreeSet**, **LightWeightMap**, **LightWeightSet**, and **PlainArray**. The types of **key** and **value** in nonlinear containers must meet the ECMA standard.
+
+
+## HashMap
+
+[HashMap](../reference/apis/js-apis-hashmap.md) is used to store a set of associated key-value (KV) pairs. In a hash map, each key is unique and corresponds to a value.
+
+**HashMap** uses generics. In a hash map, a key is located based on its hash code. The initial capacity of a hash map is 16, and it has capacity doubled in each dynamic expansion. The bottom layer of **HashMap** is implemented based on a hash table. It uses chaining to avoid collisions in hash tables.
+
+**HashMap** is faster in accessing data than [TreeMap](../reference/apis/js-apis-treemap.md), because the former accesses the keys based on the hash codes, whereas the latter stores and accesses the keys in sorted order.
+
+[HashSet](../reference/apis/js-apis-hashset.md) is implemented based on **HashMap**. The input parameter of **HashMap** consists of **key** and **value**. In **HashSet**, only the **value** object is processed.
+
+You are advised to use **HashMap** when you need to quickly access, remove, and insert KV pairs.
+
+**HashMap** provides the following Create, Read, Update, and Delete (CRUD) APIs.
+
+| Operation| Description|
+| -------- | ------ |
+| Adding elements| Use **set(key: K, value: V)** to add an element (a KV pair) to this container.|
+| Accessing elements| Use **get(key: K)** to obtain the value of the specified key.|
+| Accessing elements| Use **keys()** to return an iterator that contains all the keys in 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?: V, key?: K, map?: HashMap) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<[K,V]>** for data access.|
+| Modifying elements| Use **replace(key: K, newValue: V)** to change the value of the specified key.|
+| Modifying elements| Use **forEach(callbackFn: (value?: V, key?: K, map?: HashMap) => void, thisArg?: Object)** to modify an element in this container.|
+| Deleting elements| Use **remove(key: K)** to remove an element with the specified key.|
+| Deleting elements| Use **clear()** to clear this container.|
+
+
+## HashSet
+
+[HashSet](../reference/apis/js-apis-hashset.md) is used to store a set of values, each of which is unique in a hash set.
+
+**HashSet** uses generics. In a hash set, a value is located based on its hash code. The initial capacity of a hash set is 16, and it has capacity doubled in each dynamic expansion. The type of **value** must comply with the ECMA standard. The bottom layer of **HashSet** is implemented based on a hash table. It uses chaining to avoid collisions in hash tables.
+
+**HashSet** is implemented based on [HashMap](../reference/apis/js-apis-hashmap.md). In **HashSet**, only the **value** object is processed.
+
+Unlike [TreeSet](../reference/apis/js-apis-treeset.md), which stores and accesses data in sorted order, **HashSet** stores data in a random order. This means that **HashSet** may use a different order when storing and accessing elements. Both of them allows only unique elements. However, null values are allowed in **HashSet**, but not allowed in **TreeSet**.
+
+You are advised to use **HashSet** when you need a set that has only unique elements or need to deduplicate a set.
+
+**HashSet** provides the following CRUD APIs.
+
+| Operation| Description|
+| -------- | ------ |
+| 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\) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: HashSet\) => 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.|
+
+
+## TreeMap
+
+[TreeMap](../reference/apis/js-apis-treemap.md) is used to store a set of associated KV pairs. In a tree map, each key is unique and corresponds to a value.
+
+**TreeMap** uses generics, and the keys in a tree map are ordered. The bottom layer of **TreeMap** is a binary tree, which supports quick search of KV pairs through the children (left child and right child) of the tree. The type of **key** must comply with the ECMA standard. Keys in a tree map are stored in order. The bottom layer of **TreeMap** is implemented based on the red-black tree and supports quick insertion and removal.
+
+[HashMap](../reference/apis/js-apis-hashmap.md) is faster in accessing data than **TreeMap**, because the former accesses the keys based on the hash codes, whereas the latter stores and accesses the keys in sorted order.
+
+You are advised to use **TreeMap** when you need to store KV pairs in sorted order.
+
+**TreeMap** provides the following CRUD APIs.
+
+| Operation| Description|
+| ------- | ------ |
+| Adding elements| Use **set(key: K, value: V)** to add an element (a KV pair) to this container.|
+| Accessing elements| Use **get(key: K)** to obtain the value of the specified key.|
+| Accessing elements| Use **getFirstKey()** to obtain the first key in this container.|
+| Accessing elements| Use **getLastKey()** to obtain the last key in this container.|
+| Accessing elements| Use **keys()** to return an iterator that contains all the keys in 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?: V, key?: K, map?: TreeMap) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator\<[K,V]>** for data access.|
+| Modifying elements| Use **replace(key: K, newValue: V)** to change the value of the specified key.|
+| Modifying elements| Use **forEach(callbackFn: (value?: V, key?: K, map?: TreeMap) => void, thisArg?: Object)** to modify an element in this container.|
+| Deleting elements| Use **remove(key: K)** to remove an element with the specified key.|
+| Deleting elements| Use **clear()** to clear this container.|
+
+
+## TreeSet
+
+[TreeSet](../reference/apis/js-apis-treeset.md) is used to store a set of values, each of which is unique in a tree set.
+
+**TreeSet** uses generics, and the values in a tree set are ordered. The bottom layer of **TreeSet** is a binary tree, which supports quick search of a value through the children (left child and right child) of the tree. The type of **value** must meet the ECMA standard. Values in a tree set are stored in order. The bottom layer of **TreeSet** is implemented based on the red-black tree and supports quick insertion and removal.
+
+**TreeSet** is implemented based on [TreeMap](../reference/apis/js-apis-treemap.md). In **TreeSet**, only **value** objects are processed. **TreeSet** can be used to store values, each of which must be unique.
+
+[HashSet](../reference/apis/js-apis-hashset.md) stores data in a random order, whereas **TreeSet** stores data in sorted order. Both of them allows only unique elements. However, null values are allowed in **HashSet**, but not allowed in **TreeSet**.
+
+You are advised to use **TreeSet** when you need to store data in sorted order.
+
+**TreeSet** provides the following CRUD APIs.
+
+| Operation| Description|
+| -------- | ------ |
+| 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 **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\) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: TreeSet\) => 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.|
+
+
+## LightWeightMap
+
+[LightWeightMap](../reference/apis/js-apis-lightweightmap.md) is used to store a set of associated KV pairs. In a lightweight map, each key is unique and corresponds to a value. **LightWeightMap** uses generics and a more lightweight structure. It uses the hash code to uniquely identify a key at the bottom layer. It uses linear probing to avoid collisions. In a lightweight map, a key is located by using the hash code and binary search algorithm. The hash code is stored in an array and mapped to a key and its value in another array. The type of **key** must comply with the ECMA standard.
+
+The default initial capacity of a lightweight map is 8, and it has capacity doubled in each expansion.
+
+Compared with [HashMap](../reference/apis/js-apis-hashmap.md), which can also store KV pairs, **LightWeightMap** occupies less memory.
+
+You are advised to use **LightWeightMap** when you need to store and access **KV pairs**.
+
+**LightWeightMap** provides the following CRUD APIs.
+
+| Operation| Description|
+| -------- | ------ |
+| Adding elements| Use **set(key: K, value: V)** to add an element (a KV pair) to this container.|
+| Accessing elements| Use **get(key: K)** to obtain the value of the specified key.|
+| Accessing elements| Use **getIndexOfKey(key: K)** to obtain the index of the specified key.|
+| Accessing elements| Use **getIndexOfValue(value: V)** to obtain the index of the first occurrence of the specified value.|
+| Accessing elements| Use **keys()** to return an iterator that contains all the keys in 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 **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?: V, key?: K, map?: LightWeightMap) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<[K,V]>** for data access.|
+| Modifying elements| Use **setValueAt(index: number, newValue: V)** to change the value of an element at a given position (specified by **index**).|
+| Modifying elements| Use **forEach(callbackFn: (value?: V, key?: K, map?: LightWeightMap) => void, thisArg?: Object)** to modify an element 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.|
+
+
+## LightWeightSet
+
+[LightWeightSet](../reference/apis/js-apis-lightweightset.md) is used to store a set of values, each of which is unique in a lightweight set.
+
+**LightWeightSet** uses generics and a lightweight structure. Its default initial capacity is 8, and it has capacity doubled in each expansion. In a lightweight set, a value is located by using the hash code and binary search algorithm. The hash code is stored in an array and mapped to a value in another array. The type of **value** must comply with the ECMA standard.
+
+**LightWeightSet** uses the hash code to uniquely identify a value at the bottom layer. It uses linear probing to avoid collisions and adopts the binary search algorithm.
+
+Compared with [HashSet](../reference/apis/js-apis-hashset.md), which can also store values, **LightWeightSet** occupies less memory.
+
+You are advised to use **LightWeightSet** when you need a set that has only unique elements or need to deduplicate a set.
+
+**LightWeightSet** provides the following CRUD APIs.
+
+| Operation| Description|
+| -------- | ------ |
+| Adding elements| Use **add(obj: T)** to add a value to this container.|
+| Accessing elements| Use **getIndexOf(key: T)** to obtain the index of a key.|
+| 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\) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<T>** for data access.|
+| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: LightWeightSet\) => 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.|
+
+
+## PlainArray
+
+[PlainArray](../reference/apis/js-apis-plainarray.md) is used to store a set of associated KV pairs. In a plain array, each key is unique, corresponds to a value, and is of the number type. **PlainArray** uses generics and a more lightweight structure. In a plain array, a key is located by using the binary search algorithm and is mapped to a value in another array.
+
+The default initial capacity of a plain array is 16, and it has capacity doubled in each expansion.
+
+Both **PlainArray** and [LightWeightMap](../reference/apis/js-apis-lightweightmap.md) are used to store KV pairs in the lightweight structure. However, the key type of **PlainArray** can only be **number**.
+
+You are advised to use PlainArray when you need to store KV pairs whose keys are of the number type.
+
+**PlainArray** provides the following CRUD APIs.
+
+| Operation| Description|
+| -------- | ------ |
+| Adding elements| Use **add(key: number,value: T)** to add an element (a KV pair) to this container.|
+| Accessing elements| Use **get(key: number)** to obtain the value of the specified key.|
+| Accessing elements| Use **getIndexOfKey(key: number)** to obtain the index of the specified key.|
+| 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\) => void, thisArg?: Object)** to traverse the elements in this container.|
+| Accessing elements| Use **\[Symbol.iterator]():IterableIterator<[number, T]>** 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\) => 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.|
+| Deleting elements| Use **clear()** to clear this container.|
+
+
+## Use of Nonlinear Containers
+
+Refer to the code snippet below to add, access, and modify elements in **HashMap**, **TreeMap**, **LightWeightMap**, **Stack**, and **PlainArray**.
+
+
+```js
+// HashMap
+import HashMap from '@ohos.util.HashMap'; // Import the HashMap module.
+
+let hashMap = new HashMap();
+hashMap.set('a', 123);
+hashMap.set (4, 123);// Add an element.
+console.info(`result: ${hashMap.hasKey(4)}`); // Check whether an element is contained.
+console.info(`result: ${hashMap.get('a')}`); // Access an element.
+
+// TreeMap
+import TreeMap from '@ohos.util.TreeMap'; // Import the TreeMap module.
+
+let treeMap = new TreeMap();
+treeMap.set('a', 123);
+treeMap.set('6', 356); // Add an element.
+console.info(`result: ${treeMap.get('a')}`); // Access an element.
+console.info(`result: ${treeMap.getFirstKey()}`); // Access the first element.
+console.info(`result: ${treeMap.getLastKey()}`); // Access the last element.
+
+// LightWeightMap
+import LightWeightMap from '@ohos.util.LightWeightMap'; // Import the LightWeightMap module.
+
+let lightWeightMap = new LightWeightMap();
+lightWeightMap.set('x', 123);
+lightWeightMap.set('8', 356); // Add an element.
+console.info(`result: ${lightWeightMap.get('a')}`); // Access an element.
+console.info(`result: ${lightWeightMap.get('x')}`); // Access an element.
+console.info(`result: ${lightWeightMap.getIndexOfKey('8')}`); // Access an element.
+
+// PlainArray
+import PlainArray from '@ohos.util.PlainArray' // Import the PlainArray module.
+
+let plainArray = new PlainArray();
+plainArray.add(1, 'sdd');
+plainArray.add(2,'sff'); // Add an element.
+console.info(`result: ${plainArray.get(1)}`); // Access an element.
+console.info(`result: ${plainArray.getKeyAt(1)}`); // Access an element.
+```
diff --git a/en/application-dev/arkts-utils/single-io-development.md b/en/application-dev/arkts-utils/single-io-development.md
new file mode 100644
index 0000000000000000000000000000000000000000..b488890b42c9cb5849077fd1f00815f1a3f5ddf8
--- /dev/null
+++ b/en/application-dev/arkts-utils/single-io-development.md
@@ -0,0 +1,29 @@
+# Single I/O Task Development
+
+
+Asynchronous concurrency provided by Promise and async/await is applicable to the development of a single I/O task. The following uses the asynchronous concurrency capability to write a file as an example.
+
+
+1. Implement the logic of a single I/O task.
+
+ ```js
+ import fs from '@ohos.file.fs';
+
+ async function write(data: string, filePath: string) {
+ let file = await fs.open(filePath, fs.OpenMode.READ_WRITE);
+ fs.write(file.fd, data).then((writeLen) => {
+ fs.close(file);
+ }).catch((err) => {
+ console.error(`Failed to write data. Code is ${err.code}, message is ${err.message}`);
+ })
+ }
+ ```
+
+2. Use the asynchronous capability to invoke the single I/O task. For details about how to obtain **filePath** in the example, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths).
+
+ ```js
+ let filePath = ...; // Application file path
+ write('Hello World!', filePath).then(() => {
+ console.info('Succeeded in writing data.');
+ })
+ ```
diff --git a/en/application-dev/arkts-utils/sync-task-development.md b/en/application-dev/arkts-utils/sync-task-development.md
new file mode 100644
index 0000000000000000000000000000000000000000..8ce4290a5122b30955c94a1e9116c92f53e0ea7b
--- /dev/null
+++ b/en/application-dev/arkts-utils/sync-task-development.md
@@ -0,0 +1,173 @@
+# Synchronous Task Development
+
+
+Synchronous tasks are executed in order among multiple threads. For example, as a synchronization primitive, locks prevent data contention.
+
+
+To implement synchronous tasks, you must consider the collaboration and synchronization between multiple threads and ensure the correctness of data and the correct execution of programs.
+
+If synchronous tasks are independent of each other, you are advised to use **TaskPool**, since it focuses on single independent tasks. For example, a series of imported static methods or methods implemented in singletons are independent. If synchronous tasks are associated with each other, use **Worker**, for example, methods implemented in class objects (not singleton class objects).
+
+
+## Using TaskPool to Process Independent Synchronous Tasks
+
+**TaskPool** is recommended for scheduling independent synchronous tasks. Typical synchronous tasks are those using static methods. If a unique handle or class object constructed using a singleton points to multiple tasks and these tasks can be used between different worker threads, you can also use **TaskPool**.
+
+1. Define a concurrency function that internally calls the synchronous methods.
+
+2. Create a task, execute the task through **TaskPool**, and perform operations on the asynchronous result. Create a [task](../reference/apis/js-apis-taskpool.md#task) and call [execute()](../reference/apis/js-apis-taskpool.md#taskpoolexecute-1) to execute the task synchronously.
+
+3. Perform concurrent operations.
+
+Simulate a singleton class that contains synchronous calls.
+
+
+```ts
+// handle.ts code
+export default class Handle {
+ static getInstance() {
+ // Return a singleton object.
+ }
+
+ static syncGet() {
+ // Synchronous getter.
+ return;
+ }
+
+ static syncSet(num: number) {
+ // Synchronous setter.
+ return;
+ }
+}
+```
+
+Use **TaskPool** to call the related synchronous methods.
+
+
+```ts
+// Index.ets code
+import taskpool from '@ohos.taskpool';
+import Handle from './Handle'; // Return a static handle.
+
+// Step 1: Define a concurrency function that internally calls the synchronous methods.
+@Concurrent
+function func(num: number) {
+ // Call the synchronous wait implemented in a static class object.
+ Handle.syncSet(num);
+ // Alternatively, call the synchronous wait implemented in a singleton object.
+ Handle.getInstance().syncGet();
+ return true;
+}
+
+// Step 2: Create and execute a task.
+async function asyncGet() {
+ // Create a task and pass in the function func.
+ let task = new taskpool.Task(func, 1);
+ // Execute the task and obtain the result res.
+ let res = await taskpool.execute(task);
+ // Perform operations on the synchronous result.
+ console.info(String(res));
+}
+
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ .onClick(() => {
+ // Step 3: Perform concurrent operations.
+ asyncGet();
+ })
+ }
+ .width('100%')
+ .height('100%')
+ }
+ }
+}
+```
+
+
+## Using Worker to Process Associated Synchronous Tasks
+
+Use **Worker** when you want to schedule a series of synchronous tasks using the same handle or depending on the same class object.
+
+1. Create a **Worker** object in the main thread and receive messages from the worker thread.
+
+ ```js
+ import worker from '@ohos.worker';
+
+ @Entry
+ @Component
+ struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ .onClick(() => {
+ let w = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
+ w.onmessage = function (d) {
+ // Receive the result of the worker thread.
+ }
+ w.onerror = function (d) {
+ // Receive error information of the worker thread.
+ }
+ // Send a Set message to the worker thread.
+ w.postMessage({'type': 0, 'data': 'data'})
+ // Send a Get message to the worker thread.
+ w.postMessage({'type': 1})
+ // Destroy the worker thread.
+ w.terminate()
+ })
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+ }
+ ```
+
+2. Bind the **Worker** object in the worker thread and process the synchronous task logic.
+
+ ```js
+ // handle.ts code
+ export default class Handle {
+ syncGet() {
+ return;
+ }
+
+ syncSet(num: number) {
+ return;
+ }
+ }
+
+ // Worker.ts code
+ import worker, { ThreadWorkerGlobalScope, MessageEvents } from '@ohos.worker';
+ import Handle from './handle.ts' // Return a handle.
+
+ var workerPort : ThreadWorkerGlobalScope = worker.workerPort;
+
+ // Handle that cannot be transferred. All operations depend on this handle.
+ var handler = new Handle()
+
+ // onmessage() logic of the worker thread.
+ workerPort.onmessage = function(e : MessageEvents) {
+ switch (e.data.type) {
+ case 0:
+ handler.syncSet(e.data.data);
+ workerPort.postMessage('success set');
+ case 1:
+ handler.syncGet();
+ workerPort.postMessage('success get');
+ }
+ }
+ ```
diff --git a/en/application-dev/arkts-utils/taskpool-vs-worker.md b/en/application-dev/arkts-utils/taskpool-vs-worker.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a3dcd0557a3afbdcfba515752eeea5780f872ab
--- /dev/null
+++ b/en/application-dev/arkts-utils/taskpool-vs-worker.md
@@ -0,0 +1,164 @@
+# Comparison Between TaskPool and Worker
+
+**TaskPool** and **Worker** provide a multithread running environment for applications to process time-consuming computing tasks or resource intensive tasks, preventing these tasks from blocking the main thread. This maximizes system utilization, reduces overall resource consumption, and improves overall system performance.
+
+
+This topic compares **TaskPool** with **Worker** from two aspects: [implementation features](#implementation-feature-comparison) and [use cases](#use-case-comparison). It also describes their operating mechanisms and precautions.
+
+
+## Implementation Feature Comparison
+
+**Table 1** Comparison between TaskPool and Worker in implementation features
+
+| Item| TaskPool | Worker |
+| -------- | -------- | -------- |
+| Memory model| Threads are isolated from each other, and memory is not shared.| Threads are isolated from each other, and memory is not shared.|
+| Parameter passing mechanism| The structured clone algorithm is used for serialization and deserialization. ArrayBuffer and SharedArrayBuffer are used for parameter passing and sharing.| The structured clone algorithm is used for serialization and deserialization. ArrayBuffer and SharedArrayBuffer are used for parameter passing and sharing.|
+| Parameter passing| Parameters are directly passed in, without being encapsulated.| Only one parameter can be carried in a message object. Therefore, you must encapsulate excess parameters.|
+| Method invocation| Methods are directly passed in and called.| Messages are passed in the worker thread and the corresponding methods are called.|
+| Return value| A value is returned by default after asynchronous calling.| Messages proactively sent must be parsed and assigned by calling **onmessage()**.|
+| Lifecycle| The task pool manages its own lifecycle, without considering the load.| You are required to manage the number and lifecycle of worker threads.|
+| Maximum number of task pools| The number is automatically managed, rather than being manually configured.| A maximum of eight worker threads are supported.|
+| Maximum task execution duration| 3 minutes (excluding the time used for Promise or async/await asynchronous call, for example, the time consumed by I/O tasks such as network download and file read/write)| There is no restriction.|
+| Task priority setting| Setting the task priority is supported.| Setting the task priority is not supported.|
+| Task cancellation| Tasks that have been initiated can be canceled.| Tasks that have been initiated cannot be canceled.|
+
+
+## Use Case Comparison
+
+Both **TaskPool** and **Worker** support multithread concurrency. **TaskPool** worker threads are bound to the system scheduling priority and support load balancing (automatic scaling). **Worker** threads are manually created and do not support scheduling priority setting. Therefore, **TaskPool** provides better performance than **Worker** and is recommended in most scenarios.
+
+**TaskPool** is oriented to thread-level independent tasks, and tasks running for more than 3 minutes are automatically reclaimed by the system. **Worker** is oriented to threads and supports thread execution for a long time.
+
+Common use cases are as follows:
+
+- Use **Worker** for a task that runs for more than 3 minutes (excluding the time used for Promise or async/await asynchronous call, for example, I/O tasks such as network download and file read/write). For example, use **Worker** for a 1-hour prediction algorithm training job in the background.
+
+- Use **Worker** for a series of associated synchronous tasks. For example, use **Worker** for a series of database operations, since the same handle is required.
+
+- Use **TaskPool** for a task for which the priority needs to be set. For example, in the histogram rendering scenario in Gallery, histogram data calculated in the background is used for UI display on the foreground. This requires high-priority processing. In this case, use **TaskPool**.
+
+- Use **TaskPool** for a task that needs to be canceled frequently. For example, in the large image browsing scenario in Gallery, both images on the left and right sides of the current image are cached. When the user slides to the next image, a cache task on one side needs to be canceled. In this case, use **TaskPool**.
+
+- Use **TaskPool** for a large number of tasks or tasks with scattered scheduling points. For example, a large-scale application with multiple modules has multiple time-consuming tasks, and it is inconvenient to use eight worker threads to manage load. In this case, **TaskPool** is recommended.
+
+
+## TaskPool Operating Mechanism
+
+**Figure 1** TaskPool operating mechanism
+
+
+
+With **TaskPool**, you can encapsulate tasks in the main thread and throw the tasks to the task queue. The system selects proper worker threads to distribute and execute the tasks, and then returns the result to the main thread. **TaskPool** provides APIs to execute and cancel tasks, and set the task priority. It also minimizes system resource usage through unified thread management, dynamic scheduling, and load balancing algorithms. By default, the system starts a worker thread and increases the thread quantity as the number of tasks increases. The maximum number of worker threads that can be created depends on the number of physical cores of the device. The formula is max(3, Number of physical cores – 1). If no task is distributed for a long period of time, the system reduces the number of worker threads.
+
+
+## Worker Operating Mechanism
+
+**Figure 2** Worker operating mechanism
+
+
+
+The thread that creates the worker thread is referred to as the host thread (not necessarily the main thread, since a worker thread can also create a worker subthread). A worker thread is also named an actor thread. Each worker thread has an independent instance from the host thread, including the infrastructure, object, and code segment. The worker thread communicates with the host thread by means of message exchange. They use the serialization technique to exchange commands and data.
+
+
+## Precautions for TaskPool
+
+- A task function must be decorated with **\@Concurrent** and can be used only in .ets files.
+
+- A task function must be a common function or async function, but not a class member function or anonymous function.
+
+- A task function can use imported variables and input parameter variables only in a project created on the stage model. In a project created on the FA model, it can use input parameter variables only.
+
+- A task function in the **TaskPool** worker thread must finish the execution within 3 minutes (excluding the time used for Promise or async/await asynchronous call, for example, the duration of I/O tasks such as network download and file read/write). Otherwise, it forcibly exits.
+
+- Input parameter types in a task function must be those supported by serialization. For details, see [Common Objects](multi-thread-concurrency-overview.md#common-objects).
+
+- Parameters of the ArrayBuffer type are transferred in **TaskPool** by default. You can set the transfer list by calling [setTransferList()](../reference/apis/js-apis-taskpool.md#settransferlist10).
+
+- The context objects in different threads are different. Therefore, **TaskPool** worker threads can use only thread-safe libraries, rather than UI-related non-thread-safe libraries.
+
+- A maximum of 16 MB data can be serialized.
+
+
+## Precautions for Worker
+
+- The rules for passing in the **Worker.ts** path during the worker creation vary in different API versions. For details, see [Precautions for File Paths](#precautions-for-file-paths).
+
+- After a worker thread is created, you must manually manage its lifecycle. A maximum of eight worker threads can run simultaneously. For details, see [Lifecycle Precautions](#lifecycle-precautions).
+
+- Modules of the [ability type](../quick-start/application-package-structure-stage.md) support **Worker**, but modules of the [library type](../quick-start/application-package-structure-stage.md) do not support **Worker**.
+
+- When creating a worker thread, the **Worker.ts** file of another module cannot be used. This means that a worker cannot be called across modules.
+
+- The context objects in different threads are different. Therefore, **Worker** threads can use only thread-safe libraries, rather than UI-related non-thread-safe libraries.
+
+- A maximum of 16 MB data can be serialized.
+
+
+### Precautions for File Paths
+
+Before calling an API of the **Worker** module, you must create a **Worker** instance. The constructor function varies in different API versions.
+
+```js
+// Use the following function in API version 9 and later versions:
+const worker1 = new worker.ThreadWorker(scriptURL);
+// Use the following function in API version 8 and earlier versions:
+const worker1 = new worker.Worker(scriptURL);
+```
+
+The **Worker.ts** file path (specified by **scriptURL**) must be passed in the constructor function. By default, the **workers** directory (upper-level directory of the **Worker.ts** file) is at the same level as the **pages** directory.
+
+**Stage Model**
+
+
+The following is an example of **scriptURL** in the constructor function:
+
+```js
+// Method 1
+// In the stage model, the workers directory is at the same level as the pages directory in the entry module.
+const worker1 = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts', {name:"first worker in Stage model"});
+// In the stage model, the workers directory is a child directory of the pages directory in the entry module.
+const worker2 = new worker.ThreadWorker('entry/ets/pages/workers/MyWorker.ts');
+
+// Method 2
+// In the stage model, the workers directory is at the same level as the pages directory in the entry module, and bundlename is com.example.workerdemo.
+const worker3 = new worker.ThreadWorker('@bundle:com.example.workerdemo/entry/ets/workers/worker');
+// In the stage model, the workers directory is a child directory of the pages directory in the entry module, and bundlename is com.example.workerdemo.
+const worker4 = new worker.ThreadWorker('@bundle:com.example.workerdemo/entry/ets/pages/workers/worker');
+```
+
+
+- Based on the directory structure of the stage model project, the field meanings in method 1 are as follows:
+ - **entry**: value of the **name** attribute under **module** in the **module.json5** file.
+ - **ets**: directory for storing the ArkTS source code. It is fixed.
+ - **workers/MyWorker.ts**: path of the worker source file in the **ets** directory.
+
+- Based on the directory structure of the stage model project, the field meanings in method 2 are as follows:
+ - **\@bundle**: fixed label.
+ - **bundlename**: bundle name of the current application.
+ - **entryname**: value of the **name** attribute under **module** in the **module.json5** file.
+ - **ets**: directory for storing the ArkTS source code. It is fixed.
+ - **workerdir/workerfile**: path of the worker source file in the **ets** directory.
+
+
+**FA Model**
+
+
+The following is an example of **scriptURL** in the constructor function:
+
+```js
+// In the FA model, the workers directory is at the same level as the pages directory in the entry module.
+const worker1 = new worker.ThreadWorker('workers/worker.js', {name:'first worker in FA model'});
+// In the FA model, the workers directory is at the same level as the parent directory of the pages directory in the entry module.
+const worker2 = new worker.ThreadWorker('../workers/worker.js');
+```
+
+
+### Lifecycle Precautions
+
+- Creating and terminating worker threads consume performance. Therefore, you are advised to manage available workers and reuse them. The worker threads keep running even when they are idle. Therefore, when a worker thread is not required, call [terminate()](../reference/apis/js-apis-worker.md#terminate9) interface or [parentPort.close()](../reference/apis/js-apis-worker.md#close9) to destroy it. If a worker thread is destroyed or being destroyed, an error is thrown when it is called.
+
+
+- A maximum of eight worker threads can co-exist.
+ - In API version 8 and earlier versions, when the number of worker threads exceeds the upper limit, the error "Too many workers, the number of workers exceeds the maximum." is thrown.
+ - Since API version 9, when the number of worker threads exceeds the upper limit, the error "Worker initialization failure, the number of workers exceeds the maximum." is thrown.
diff --git a/en/application-dev/arkts-utils/xml-conversion.md b/en/application-dev/arkts-utils/xml-conversion.md
new file mode 100644
index 0000000000000000000000000000000000000000..96dc727635ea4449edd3bdc41e5ec016b268eca9
--- /dev/null
+++ b/en/application-dev/arkts-utils/xml-conversion.md
@@ -0,0 +1,92 @@
+# XML Conversion
+
+
+Converting XML text into JavaScript objects makes it easier to process and manipulate data. In addition, JavaScript objects are more suitable than XML text for JavaScript applications.
+
+
+The common library provides the **ConvertXML** class to convert XML text into JavaScript objects. The input is XML strings and conversion options, and the output is a JavaScript object. For details about the conversion options, see the API reference [@ohos.convertxml (XML-to-JavaScript Conversion)](../reference/apis/js-apis-convertxml.md).
+
+
+## Precautions
+
+To ensure successful XML parsing and conversion, the input XML data must comply with the standard format.
+
+
+## How to Develop
+
+The following steps walk you through on how to convert an XML file into a JavaScript object to obtain the tag values.
+
+1. Import the **convertxml** module.
+
+ ```js
+ import convertxml from '@ohos.convertxml';
+ ```
+
+2. Pass in an XML file to be converted and set conversion options.
+
+ ```js
+ let xml =
+ '' +
+ '' +
+ ' Happy ' +
+ ' Work ' +
+ ' Play ' +
+ ' ';
+ let options = {
+ // trim: false, indicating that spaces before and after the text are not deleted after conversion.
+ // declarationKey: "_declaration", indicating that _declaration is used to identify the file declaration after conversion.
+ // instructionKey: "_instruction", indicating that _instruction is used to identify instructions after conversion.
+ // attributesKey: "_attributes", indicating that _attributes is used to identify attributes after conversion.
+ // textKey: "_text", indicating that _text is used to identify tag values after conversion.
+ // cdataKey: "_cdata", indicating that _cdata is used to identify unparsed data after conversion.
+ // docTypeKey: "_doctype", indicating that _doctype is used to identify documents after conversion.
+ // commentKey: "_comment", indicating that _comment is used to identify comments after conversion.
+ // parentKey: "_parent", indicating that _parent is used to identify parent classes after conversion.
+ // typeKey: "_type", indicating that _type is used to identify types after conversion.
+ // nameKey: "_name", indicating that _name is used to identify tag names after conversion.
+ // elementsKey: "_elements", indicating that _elements is used to identify elements after conversion.
+ trim: false,
+ declarationKey: "_declaration",
+ instructionKey: "_instruction",
+ attributesKey: "_attributes",
+ textKey: "_text",
+ cdataKey: "_cdata",
+ docTypeKey: "_doctype",
+ commentKey: "_comment",
+ parentKey: "_parent",
+ typeKey: "_type",
+ nameKey: "_name",
+ elementsKey: "_elements"
+ }
+ ```
+
+3. Call the conversion function and print the result.
+
+ ```js
+ let conv = new convertxml.ConvertXML();
+ let result = conv.convertToJSObject(xml, options);
+ let strRes = JSON.stringify(result); // Convert the JavaScript object into a JSON string for explicit output.
+ console.info(strRes);
+ // Alternatively, directly process the JavaScript object to obtain the tag values.
+ let title = result['_elements'][0]['_elements'][0]['_elements'][0]['_text']; // Parse the value of the tag.
+ let todo = result['_elements'][0]['_elements'][1]['_elements'][0]['_text']; // Parse the value of the tag.
+ let todo2 = result['_elements'][0]['_elements'][2]['_elements'][0]['_text']; // Parse the value of the tag.
+ console.info(title); // Happy
+ console.info(todo); // Work
+ console.info(todo2); // Play
+ ```
+
+ The output is as follows:
+
+
+ ```js
+ strRes:
+ {"_declaration":{"_attributes":{"version":"1.0","encoding":"utf-8"}},"_elements":[{"_type":"element","_name":"note",
+ "_attributes":{"importance":"high","logged":"true"},"_elements":[{"_type":"element","_name":"title",
+ "_elements":[{"_type":"text","_text":"Happy"}]},{"_type":"element","_name":"todo",
+ "_elements":[{"_type":"text","_text":"Work"}]},{"_type":"element","_name":"todo",
+ "_elements":[{"_type":"text","_text":"Play"}]}]}]}
+ title:Happy
+ todo:Work
+ todo2:Play
+ ```
diff --git a/en/application-dev/arkts-utils/xml-generation.md b/en/application-dev/arkts-utils/xml-generation.md
new file mode 100644
index 0000000000000000000000000000000000000000..d05cd9779255c6dfa51a9d4bb4556e2467c92c1c
--- /dev/null
+++ b/en/application-dev/arkts-utils/xml-generation.md
@@ -0,0 +1,82 @@
+# XML Generation
+
+
+XML can be used as a data exchange format, which is supported by a wealth of systems and applications. For example, web services can transfer structured data in XML format.
+
+
+XML can also be used as a message passing format for communication between nodes in a distributed system.
+
+
+## Precautions
+
+- XML tags must appear in pairs: one start tag and one end tag.
+
+- XML tags are case sensitive. The start tag and end tag must use the same case.
+
+
+## How to Develop
+
+The **xml** module provides the **XmlSerializer** class to generate XML files. The input is an object of the ArrayBuffer or DataView type with a fixed length, which is used to store the output XML data.
+
+You can call different to write different types of content. For example, call **startElement(name: string)** to write the start tag and **setText(text: string)** to write a tag value.
+
+For details about the APIs of the **XML** module, see [@ohos.xml (XML Parsing and Generation)](../reference/apis/js-apis-xml.md).
+
+The following steps walk you through on how to generate an XML file.
+
+1. Import the modules.
+
+ ```js
+ import xml from '@ohos.xml';
+ import util from '@ohos.util';
+ ```
+
+2. Create a buffer and create an **XmlSerializer** object, either based on an object of the ArrayBuffer or DataView type.
+
+ ```js
+ // 1. Create an XmlSerializer object based on an object of the ArrayBuffer type.
+ let arrayBuffer = new ArrayBuffer(2048); // Create a 2048-byte object of the ArrayBuffer type.
+ let thatSer = new xml.XmlSerializer (arrayBuffer); // Create an XmlSerializer object based on the object of the ArrayBuffer type.
+
+ // 2. Create an XmlSerializer object based on an object of the DataView type.
+ let arrayBuffer = new ArrayBuffer(2048); // Create a 2048-byte object of the ArrayBuffer type.
+ let dataView = new DataView(arrayBuffer); // Use an object of the DataView type to operate the object of the ArrayBuffer type.
+ let thatSer = new xml.XmlSerializer (dataView); // Create an XmlSerializer object based on the object of the DataView type.
+ ```
+
+3. Call the functions to generate an XML file.
+
+ ```js
+ thatSer.setDeclaration(); // Write the XML file declaration.
+ thatSer.startElement('bookstore'); // Write the start flag.
+ thatSer.startElement('book'); // Write the start tag of a nested element.
+ thatSer.setAttributes('category', 'COOKING'); // Write the attributes and attribute values.
+ thatSer.startElement('title');
+ thatSer.setAttributes('lang', 'en');
+ thatSer.setText('Everyday'); // Write the tag value.
+ thatSer.endElement(); // Write the end flag.
+ thatSer.startElement('author');
+ thatSer.setText('Giada');
+ thatSer.endElement();
+ thatSer.startElement('year');
+ thatSer.setText('2005');
+ thatSer.endElement();
+ thatSer.endElement();
+ thatSer.endElement();
+ ```
+
+4. Use **Uint8Array** to operate the object of the ArrayBuffer type, and use **TextDecoder** to decode the Uint8Array.
+
+ ```js
+ let view = new Uint8Array(arrayBuffer); // Use Uint8Array to read data from the object of the ArrayBuffer type.
+ let textDecoder = util.TextDecoder.create(); // Call the TextDecoder class of the util module.
+ let res = textDecoder.decodeWithStream (view); // Decode the view.
+ console.info(res);
+ ```
+
+ The output is as follows:
+
+
+ ```js
+ \r\n \r\n Everyday \r\n Giada \r\n 2005 \r\n \r\n
+ ```
diff --git a/en/application-dev/arkts-utils/xml-overview.md b/en/application-dev/arkts-utils/xml-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..d376fea2134fbdac8a02d5a4c8e4ffdfdb99eb4d
--- /dev/null
+++ b/en/application-dev/arkts-utils/xml-overview.md
@@ -0,0 +1,23 @@
+# XML Overview
+
+
+Extensible Markup Language (XML) is a markup language used to describe data. It aims to provide a common way to transmit and store data, especially data frequently used in web applications. XML does not predefine tags. As a result, it is more flexible and widely used.
+
+
+An XML file consists of elements, attributes, and content.
+
+
+- An element refers to a tag pair that contains text, attributes, or other elements.
+
+- Attributes provide additional information about an element.
+
+- Content is the data or sub-element contained in an element.
+
+
+XML supports the use of XML Schema Definition (XSD) or Document Type Definition (DTD) for defining the document structure. This allows you to customize rules to verify whether an XML document is in the expected format.
+
+
+XML also supports features such as namespaces, entity references, comments, and processing instructions, making it easy to adapt to diverse data requirements.
+
+
+The common library provides XML-related basic capabilities, including [XML generation](xml-generation.md), [XML parsing](xml-parsing.md), and [XML conversion](xml-conversion.md).
diff --git a/en/application-dev/arkts-utils/xml-parsing.md b/en/application-dev/arkts-utils/xml-parsing.md
new file mode 100644
index 0000000000000000000000000000000000000000..89ed22585be75803b281517d390f400ceeda9d4d
--- /dev/null
+++ b/en/application-dev/arkts-utils/xml-parsing.md
@@ -0,0 +1,271 @@
+# XML Parsing
+
+
+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 ArrayBuffer or DataView type containing XML text, and the output is the parsed information.
+
+
+**Table 1** XML parsing options
+
+| Name| Type| Mandatory| Description|
+| -------- | -------- | -------- | -------- |
+| supportDoctype | boolean | No| Whether to ignore the document type. The default value is **false**, indicating that the document type is parsed.|
+| ignoreNameSpace | boolean | No| Whether to ignore the namespace. The default value is **false**, indicating that the namespace is parsed.|
+| tagValueCallbackFunction | (name: string, value: string) => boolean | No| Callback used to return **tagValue**, which consists of a tag and its value. The default value is **null**, indicating that XML tags and tag values are not parsed.|
+| attributeValueCallbackFunction | (name: string, value: string) => boolean | No| Callback used to return **attributeValue**, which consists of an attribute and its value. The default value is **null**, indicating that XML attributes and attribute values are not parsed.|
+| tokenValueCallbackFunction | (eventType: EventType, value: ParseInfo) => boolean | No| Callback used to return **tokenValue**, which consists of the event type and the attributes of **parseInfo**. The default value is **null**, indicating that the event type and the attributes of **parseInfo** are not parsed.|
+
+
+## Precautions
+
+- To ensure successful XML parsing and conversion, the input XML data must comply with the standard format.
+
+- Currently, parsing a given node is not supported.
+
+
+## Parsing XML Tags and Tag Values
+
+1. Import the modules.
+
+ ```js
+ import xml from '@ohos.xml';
+ import util from '@ohos.util'; // Use the API provided by the util module to encode the file.
+ ```
+
+2. Create an **XmlPullParser** object.
+
+ The **XmlPullParser** object can be created based on an object of the ArrayBuffer or DataView type.
+
+
+ ```js
+ let strXml =
+ '' +
+ '' +
+ 'Play ' +
+ 'Work ' +
+ ' ';
+ let textEncoder = new util.TextEncoder();
+ let arrBuffer = textEncoder.encodeInto(strXml); // Encode the data to prevent garbled characters.
+ // 1. Create an XmlPullParser object based on an object of the ArrayBuffer type.
+ let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
+
+ // 2. Create an XmlPullParser object based on an object of the DataView type.
+ let dataView = new DataView(arrBuffer.buffer);
+ let that = new xml.XmlPullParser(dataView, 'UTF-8');
+ ```
+
+3. Customize a callback function. In this example, the tag and tag value are directly printed.
+
+ ```js
+ let str = '';
+ function func(name, value){
+ str = name + value;
+ console.info(str);
+ return true; // The value true means to continue parsing, and false means to stop parsing.
+ }
+ ```
+
+4. Set parsing options and call the **parse()** function.
+
+ ```js
+ let options = {supportDoctype:true, ignoreNameSpace:true, tagValueCallbackFunction:func};
+ that.parse(options);
+ ```
+
+ The output is as follows:
+
+
+ ```js
+ note
+ title
+ Play
+ title
+ lens
+ Work
+ lens
+ note
+ ```
+
+
+## Parsing XML Attributes and Attribute Values
+
+1. Import the modules.
+
+ ```js
+ import xml from '@ohos.xml';
+ import util from '@ohos.util'; // Use the API provided by the util module to encode the file.
+ ```
+
+2. Create an **XmlPullParser** object.
+
+ ```js
+ let strXml =
+ '' +
+ '' +
+ ' Play ' +
+ ' Happy ' +
+ ' Work ' +
+ ' ';
+ let textEncoder = new util.TextEncoder();
+ let arrBuffer = textEncoder.encodeInto(strXml); // Encode the data to prevent garbled characters.
+ let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
+ ```
+
+3. Customize a callback function. In this example, the attribute and attribute value are directly printed.
+
+ ```js
+ let str = '';
+ function func(name, value){
+ str += name + ' ' + value + ' ';
+ return true; // The value true means to continue parsing, and false means to stop parsing.
+ }
+ ```
+
+4. Set parsing options and call the **parse()** function.
+
+ ```js
+ let options = {supportDoctype:true, ignoreNameSpace:true, attributeValueCallbackFunction:func};
+ that.parse(options);
+ console.info(str); // Print all attributes and their values at a time.
+ ```
+
+ The output is as follows:
+
+
+ ```js
+ importance high logged true // Attributes and attribute values of the note node
+ ```
+
+
+## Parsing XML Event Types and Element Depths
+
+1. Import the modules.
+
+ ```js
+ import xml from '@ohos.xml';
+ import util from '@ohos.util'; // Use the API provided by the util module to encode the file.
+ ```
+
+2. Create an **XmlPullParser** object.
+
+ ```js
+ let strXml =
+ '' +
+ '' +
+ 'Play ' +
+ ' ';
+ let textEncoder = new util.TextEncoder();
+ let arrBuffer = textEncoder.encodeInto(strXml); // Encode the data to prevent garbled characters.
+ let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
+ ```
+
+3. Customize a callback function. In this example, the event type and element depth are directly printed.
+
+ ```js
+ let str = '';
+ function func(name, value){
+ str = name +' ' + value.getDepth(); // getDepth is called to obtain the element depth.
+ console.info(str)
+ return true; // The value true means to continue parsing, and false means to stop parsing.
+ }
+ ```
+
+4. Set parsing options and call the **parse()** function.
+
+ ```js
+ let options = {supportDoctype:true, ignoreNameSpace:true, tokenValueCallbackFunction:func};
+ that.parse(options);
+ ```
+
+ The output is as follows:
+
+
+ ```js
+ 0 0 // 0: . The event type value of START_DOCUMENT is 0. 0: The depth is 0.
+ 2 1 // 2: . The event type value of START_TAG is 2. 1: The depth is 1.
+ 2 2 // 2: . The event type value of START_TAG is 2. 2: The depth is 2.
+ 4 2 // 4: Play. The event type value of TEXT is 4. 2: The depth is 2.
+ 3 2 // 3: . The event type value of END_TAG is 3. 2: The depth is 2.
+ 3 1 // 3: . The event type value of END_TAG is 3. 1: The depth is 1 (corresponding to ).
+ 1 0 // 1: The event type value of END_DOCUMENT is 1. 0: The depth is 0.
+ ```
+
+
+## Example Scenario
+
+The following uses invoking all parsing options as an example to describe how to parse XML tags, attributes, and event types.
+
+
+```js
+import xml from '@ohos.xml';
+import util from '@ohos.util';
+
+let strXml =
+ '' +
+ '' +
+ 'Everyday ' +
+ 'Giada ' +
+ ' ';
+let textEncoder = new util.TextEncoder();
+let arrBuffer = textEncoder.encodeInto(strXml);
+let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
+let str = '';
+
+function tagFunc(name, value) {
+ str = name + value;
+ console.info('tag-' + str);
+ return true;
+}
+
+function attFunc(name, value) {
+ str = name + ' ' + value;
+ console.info('attri-' + str);
+ return true;
+}
+
+function tokenFunc(name, value) {
+ str = name + ' ' + value.getDepth();
+ console.info('token-' + str);
+ return true;
+}
+
+let options = {
+ supportDocType: true,
+ ignoreNameSpace: true,
+ tagValueCallbackFunction: tagFunc,
+ attributeValueCallbackFunction: attFunc,
+ tokenValueCallbackFunction: tokenFunc
+};
+that.parse(options);
+
+```
+
+The output is as follows:
+
+
+```js
+tag-
+token-0 0
+tag-book
+attri-category COOKING
+token-2 1
+tag-title
+attri-lang en
+token-2 2
+tag-Everyday
+token-4 2
+tag-title
+token-3 2
+tag-author
+token-2 2
+tag-Giada
+token-4 2
+tag-author
+token-3 2
+tag-book
+token-3 1
+tag-
+token-1 0
+```
diff --git a/en/application-dev/connectivity/Readme-EN.md b/en/application-dev/connectivity/Readme-EN.md
index c09ca21b6d0814bd1cd2cecb95b0d2896fada8c4..1a391bd7af03ae3c5d01eb01e14b66efd1f0c565 100755
--- a/en/application-dev/connectivity/Readme-EN.md
+++ b/en/application-dev/connectivity/Readme-EN.md
@@ -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)
diff --git a/en/application-dev/connectivity/http-request.md b/en/application-dev/connectivity/http-request.md
index 1bb784cf96fb1d74dcbafed54498435f505814b6..a0fa4102864ba2403e7a6826f3ca3b872b5a80dd 100644
--- a/en/application-dev/connectivity/http-request.md
+++ b/en/application-dev/connectivity/http-request.md
@@ -1,6 +1,6 @@
# 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()10+ | Initiates an HTTP network request based on the URL and returns a streaming response.|
+| requestInStream()10+ | 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'\)10+ | Unregisters the observer for events indicating receiving of HTTP streaming responses. |
| on\('dataEnd'\)10+ | Registers an observer for events indicating completion of receiving HTTP streaming responses. |
| off\('dataEnd'\)10+ | Unregisters the observer for events indicating completion of receiving HTTP streaming responses.|
-| on\('dataProgress'\)10+ | Registers an observer for events indicating progress of receiving HTTP streaming responses. |
-| off\('dataProgress'\)10+ | Unregisters the observer for events indicating progress of receiving HTTP streaming responses.|
+| on\('dataReceiveProgress'\)10+ | Registers an observer for events indicating progress of receiving HTTP streaming responses. |
+| off\('dataReceiveProgress'\)10+ | 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)
diff --git a/en/application-dev/connectivity/ipc-rpc-development-guideline.md b/en/application-dev/connectivity/ipc-rpc-development-guideline.md
index b9bbb0608dfb83ba6d2198b063e68c4b324bbd88..14016ef5da297361bd4a17a3d278357060590784 100644
--- a/en/application-dev/connectivity/ipc-rpc-development-guideline.md
+++ b/en/application-dev/connectivity/ipc-rpc-development-guideline.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/connectivity/net-connection-manager.md b/en/application-dev/connectivity/net-connection-manager.md
index c443c93759caddbc5203b65022426882c0bb960b..f3b945ab0970786000ab8b04adfe90592a11e0d1 100644
--- a/en/application-dev/connectivity/net-connection-manager.md
+++ b/en/application-dev/connectivity/net-connection-manager.md
@@ -1,10 +1,11 @@
# 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.
diff --git a/en/application-dev/connectivity/net-ethernet.md b/en/application-dev/connectivity/net-ethernet.md
index 18f20a7fd7e1a4c9516386c543c9521522df5f66..76ae1ee28078520b9d70796f71fd2b9236f47959 100644
--- a/en/application-dev/connectivity/net-ethernet.md
+++ b/en/application-dev/connectivity/net-ethernet.md
@@ -1,10 +1,11 @@
# 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**
diff --git a/en/application-dev/connectivity/net-mdns.md b/en/application-dev/connectivity/net-mdns.md
index de7982a5c03908a70e4005bdc5fbea3584c435f5..75da959da8c4b1fc55aa0afca1cf0dcd945b86bb 100644
--- a/en/application-dev/connectivity/net-mdns.md
+++ b/en/application-dev/connectivity/net-mdns.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/connectivity/net-sharing.md b/en/application-dev/connectivity/net-sharing.md
index 4072217d9ced5d99b2052b5db8ccb8333fcb7023..f2b2e6ac21362691ede111db8b16316fa9fd32cb 100644
--- a/en/application-dev/connectivity/net-sharing.md
+++ b/en/application-dev/connectivity/net-sharing.md
@@ -1,10 +1,11 @@
# 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
diff --git a/en/application-dev/connectivity/net-statistics.md b/en/application-dev/connectivity/net-statistics.md
new file mode 100644
index 0000000000000000000000000000000000000000..6df8800dd479b48c32619514b8e6b90d5c776330
--- /dev/null
+++ b/en/application-dev/connectivity/net-statistics.md
@@ -0,0 +1,156 @@
+# Traffic Management
+
+## 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).
+
+Its functions include:
+
+- Obtaining real-time traffic data by NIC or UID
+- Obtaining historical traffic data by NIC or UID
+- 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.
+
+## Available APIs
+
+For the complete list of APIs and example code, see [Traffic Management](../reference/apis/js-apis-net-statistics.md).
+
+| Type| API| Description|
+| ---- | ---- | ---- |
+| ohos.net.statistics | getIfaceRxBytes(nic: string, callback: AsyncCallback\): void; |Obtains the real-time downlink data traffic of the specified NIC. |
+| ohos.net.statistics | getIfaceTxBytes(nic: string, callback: AsyncCallback\): void; |Obtains the real-time uplink data traffic of the specified NIC. |
+| ohos.net.statistics | getCellularRxBytes(callback: AsyncCallback\): void; |Obtains the real-time downlink data traffic of the cellular network.|
+| ohos.net.statistics | getCellularTxBytes(callback: AsyncCallback\): void; |Obtains the real-time uplink data traffic of the cellular network.|
+| ohos.net.statistics | getAllRxBytes(callback: AsyncCallback\): void; |Obtains the real-time downlink data traffic of the all NICs. |
+| ohos.net.statistics | getAllTxBytes(callback: AsyncCallback\): void; |Obtains the real-time uplink data traffic of the all NICs. |
+| ohos.net.statistics | getUidRxBytes(uid: number, callback: AsyncCallback\): void; |Obtains the real-time downlink data traffic of the specified application. |
+| ohos.net.statistics | getUidTxBytes(uid: number, callback: AsyncCallback\): void; |Obtains the real-time uplink data traffic of the specified application. |
+| ohos.net.statistics | getTrafficStatsByIface(ifaceInfo: IfaceInfo, callback: AsyncCallback\): void; |Obtains the historical data traffic of the specified NIC. |
+| ohos.net.statistics | getTrafficStatsByUid(uidInfo: UidInfo, callback: AsyncCallback\): void; |Obtains the historical data traffic of the specified application. |
+| ohos.net.statistics | on(type: 'netStatsChange', callback: Callback\<{ iface: string, uid?: number }>): void |Subscribes to traffic change events.|
+| ohos.net.statistics | off(type: 'netStatsChange', callback?: Callback\<{ iface: string, uid?: number }>): void; |Unsubscribes from traffic change events.|
+
+## Obtaining Real-Time Traffic Data by NIC or UID
+
+1. Obtain the real-time data traffic of the specified NIC.
+2. Obtain the real-time data traffic of the cellular network.
+3. Obtain the real-time data traffic of all NICs.
+4. Obtain the real-time data traffic of the specified application.
+
+```js
+// Import the statistics namespace from @ohos.net.statistics.
+import statistics from '@ohos.net.statistics'
+
+// Obtain the real-time downlink data traffic of the specified NIC.
+statistics.getIfaceRxBytes("wlan0", (error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time uplink data traffic of the specified NIC.
+statistics.getIfaceTxBytes("wlan0", (error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time downlink data traffic of the cellular network.
+statistics.getCellularRxBytes((error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time uplink data traffic of the cellular network.
+statistics.getCellularTxBytes((error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time downlink data traffic of the all NICs.
+statistics.getAllRxBytes((error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time uplink data traffic of the all NICs.
+statistics.getAllTxBytes((error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time downlink data traffic of the specified application.
+let uid = 20010038;
+statistics.getUidRxBytes(uid, (error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+
+// Obtain the real-time uplink data traffic of the specified application.
+let uid = 20010038;
+statistics.getUidTxBytes(uid, (error, stats) => {
+ console.log(JSON.stringify(error))
+ console.log(JSON.stringify(stats))
+})
+```
+
+## Obtaining Historical Traffic Data by NIC or UID
+
+1. Obtain the historical data traffic of the specified NIC.
+2. Obtain the historical data traffic of the specified application.
+
+```js
+let ifaceInfo = {
+ iface: "wlan0",
+ startTime: 1685948465,
+ endTime: 16859485670
+}
+// Obtain the historical data traffic of the specified NIC.
+statistics.getTrafficStatsByIface(ifaceInfo), (error, statsInfo) => {
+ console.log(JSON.stringify(error))
+ console.log("getTrafficStatsByIface bytes of received = " + JSON.stringify(statsInfo.rxBytes));
+ console.log("getTrafficStatsByIface bytes of sent = " + JSON.stringify(statsInfo.txBytes));
+ console.log("getTrafficStatsByIface packets of received = " + JSON.stringify(statsInfo.rxPackets));
+ console.log("getTrafficStatsByIface packets of sent = " + JSON.stringify(statsInfo.txPackets));
+});
+
+let uidInfo = {
+ ifaceInfo: {
+ iface: "wlan0",
+ startTime: 1685948465,
+ endTime: 16859485670
+ },
+ uid: 20010037
+}
+// Obtain the historical data traffic of the specified application.
+statistics.getTrafficStatsByUid(uidInfo), (error, statsInfo) => {
+ console.log(JSON.stringify(error))
+ console.log("getTrafficStatsByUid bytes of received = " + JSON.stringify(statsInfo.rxBytes));
+ console.log("getTrafficStatsByUid bytes of sent = " + JSON.stringify(statsInfo.txBytes));
+ console.log("getTrafficStatsByUid packets of received = " + JSON.stringify(statsInfo.rxPackets));
+ console.log("getTrafficStatsByUid packets of sent = " + JSON.stringify(statsInfo.txPackets));
+});
+
+```
+
+## Subscribing to Traffic Change Events
+
+1. Subscribe to traffic change events.
+2. Unsubscribe from traffic change events.
+
+```js
+
+let callback = data => {
+ console.log("on netStatsChange, data:" + JSON.stringify(data));
+}
+// Subscribe to traffic change events.
+statistics.on('netStatsChange', callback);
+
+// Unsubscribe from traffic change events. You can pass the callback of the **on** function if you want to unsubscribe from a certain type of event. If you do not pass the callback, you will unsubscribe from all events.
+statistics.off('netStatsChange', callback);
+statistics.off('netStatsChange');
+
+```
diff --git a/en/application-dev/connectivity/net-vpn.md b/en/application-dev/connectivity/net-vpn.md
new file mode 100644
index 0000000000000000000000000000000000000000..a93b00b932bdec33de7cb45764474c163ed456ce
--- /dev/null
+++ b/en/application-dev/connectivity/net-vpn.md
@@ -0,0 +1,363 @@
+# 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\): void | Establishes a VPN. This API uses an asynchronous callback to return the result.|
+| ohos.net.vpn | protect(socketFd: number, callback: AsyncCallback\): void | Enables VPN tunnel protection. This API uses an asynchronous callback to return the result.|
+| ohos.net.vpn | destroy(callback: AsyncCallback\): 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#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);
+}
+```
diff --git a/en/application-dev/connectivity/socket-connection.md b/en/application-dev/connectivity/socket-connection.md
index 109b63fdb5fdcae98e23882b32018d4a03435f55..fe8ab1f141e3525de46985ba113eee364adac723 100644
--- a/en/application-dev/connectivity/socket-connection.md
+++ b/en/application-dev/connectivity/socket-connection.md
@@ -1,8 +1,8 @@
# 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.
+The Socket Connection module allows an application to transmit data over a socket connection through the TCP, UDP, or TLS protocol.
## Basic Concepts
@@ -13,10 +13,11 @@ The Socket Connection module allows an application to transmit data over a Socke
## When to Use
-Applications transmit data over TCP, UDP, or TLS Socket connections. The main application scenarios are as follows:
+Applications transmit data over TCP, UDP, or TLS socket connections. The main application scenarios are as follows:
-- Implementing data transmission over TCP/UDP Socket connections
-- Implementing encrypted data transmission over TLS Socket connections
+- Implementing data transmission over TCP socket or UDP socket connections
+- Implementing data transmission over TCP socket server connections
+- Implementing encrypted data transmission over TLS socket connections
## Available APIs
@@ -28,72 +29,75 @@ Socket connection functions are mainly implemented by the **socket** module. The
| -------- | -------- |
| constructUDPSocketInstance() | Creates a **UDPSocket** object.|
| constructTCPSocketInstance() | Creates a **TCPSocket** object.|
+| constructTCPSocketServerInstance() | Creates a **TCPSocketServer** object.|
+| listen() | Listens for and accepts TCP socket connections established over the socket. (This API is applicable only to TCP.)|
| bind() | Binds the IP address and port number.|
| send() | Sends data.|
-| close() | Closes a Socket connection.|
-| getState() | Obtains the Socket connection status.|
+| close() | Closes a socket connection.|
+| getState() | Obtains the socket connection status.|
| connect() | Connects to the specified IP address and port. This function is supported only for TCP.|
-| getRemoteAddress() | Obtains the peer address of the Socket connection. This function is supported only for TCP. The **connect** API must have been called before you use this API.|
-| on(type: 'message') | Subscribes to **message** events of the Socket connection.|
-| off(type: 'message') | Unsubscribes from **message** events of the Socket connection.|
-| on(type: 'close') | Subscribes to **close** events of the Socket connection.|
-| off(type: 'close') | Unsubscribes from **close** events of the Socket connection.|
-| on(type: 'error') | Subscribes to **error** events of the Socket connection.|
-| off(type: 'error') | Unsubscribes from **error** events of the Socket connection.|
-| on(type: 'listening') | Subscribes to **listening** events of the UDP Socket connection. |
-| off(type: 'listening') | Unsubscribes from **listening** events of the UDP Socket connection. |
-| on(type: 'connect') | Subscribes to **connect** events of the TCP Socket connection. |
-| off(type: 'connect') | Unsubscribes from **connect** events of the TCP Socket connection.|
-
-TLS Socket connection functions are mainly provided by the **tls_socket** module. The following table describes the related APIs.
+| getRemoteAddress() | Obtains the peer address of the socket connection. This function is supported only for TCP. The **connect** API must have been called before you use this API.|
+| setExtraOptions() | Sets other properties of the socket connection.|
+| on(type: 'message') | Subscribes to **message** events of the socket connection.|
+| off(type: 'message') | Unsubscribes from **message** events of the socket connection.|
+| on(type: 'close') | Subscribes to **close** events of the socket connection.|
+| off(type: 'close') | Unsubscribes from **close** events of the socket connection.|
+| on(type: 'error') | Subscribes to **error** events of the socket connection.|
+| off(type: 'error') | Unsubscribes from **error** events of the socket connection.|
+| on(type: 'listening') | Subscribes to **listening** events of the UDP socket connection. |
+| off(type: 'listening') | Unsubscribes from **listening** events of the UDP socket connection. |
+| on(type: 'connect') | Subscribes to **connect** events of the TCP socket connection. |
+| off(type: 'connect') | Unsubscribes from **connect** events of the TCP socket connection.|
+
+TLS socket connection functions are mainly provided by the **tls_socket** module. The following table describes the related APIs.
| API| Description|
| -------- | -------- |
| constructTLSSocketInstance() | Creates a **TLSSocket** object.|
| bind() | Binds the IP address and port number.|
-| close(type: 'error') | Closes a Socket connection.|
+| close(type: 'error') | Closes a socket connection.|
| connect() | Sets up a connection to the specified IP address and port number.|
| getCertificate() | Obtains an object representing the local certificate.|
| getCipherSuite() | Obtains a list containing information about the negotiated cipher suite.|
| getProtocol() | Obtains a string containing the SSL/TLS protocol version negotiated for the current connection.|
-| getRemoteAddress() | Obtains the peer address of the TLS Socket connection.|
+| getRemoteAddress() | Obtains the peer address of the TLS socket connection.|
| getRemoteCertificate() | Obtains an object representing a peer certificate.|
| getSignatureAlgorithms() | Obtains a list containing signature algorithms shared between the server and client, in descending order of priority.|
-| getState() | Obtains the TLS Socket connection status.|
-| off(type: 'close') | Unsubscribes from **close** events of the TLS Socket connection.|
-| off(type: 'error') | Unsubscribes from **error** events of the TLS Socket connection.|
-| off(type: 'message') | Unsubscribes from **message** events of the TLS Socket connection.|
-| on(type: 'close') | Subscribes to **close** events of the TLS Socket connection.|
-| on(type: 'error') | Subscribes to **error** events of the TLS Socket connection.|
-| on(type: 'message') | Subscribes to **message** events of the TLS Socket connection.|
+| getState() | Obtains the TLS socket connection status.|
+| off(type: 'close') | Unsubscribes from **close** events of the TLS socket connection.|
+| off(type: 'error') | Unsubscribes from **error** events of the TLS socket connection.|
+| off(type: 'message') | Unsubscribes from **message** events of the TLS socket connection.|
+| on(type: 'close') | Subscribes to **close** events of the TLS socket connection.|
+| on(type: 'error') | Subscribes to **error** events of the TLS socket connection.|
+| on(type: 'message') | Subscribes to **message** events of the TLS socket connection.|
| send() | Sends data.|
-| setExtraOptions() | Sets other properties of the TLS Socket connection.|
+| setExtraOptions() | Sets other properties of the TLS socket connection.|
-## Transmitting Data over TCP/UDP Socket Connections
+## Transmitting Data over TCP Socket or UDP Socket Connections
-The implementation is similar for UDP Socket and TCP Socket connections. The following uses data transmission over a TCP Socket connection as an example.
+The implementation is similar for UDP socket and TCP socket connections. The following uses data transmission over a TCP socket connection as an example.
1. Import the required **socket** module.
-2. Create a **TCPSocket** object.
+2. Create a TCP socket connection. A **TCPSocket** object is returned.
-3. (Optional) Subscribe to TCP Socket connection events.
+3. (Optional) Subscribe to TCP socket connection events.
4. Bind the IP address and port number. The port number can be specified or randomly allocated by the system.
5. Set up a connection to the specified IP address and port number.
-6. Send data.
+6. Send data over the connection.
-7. Enable the TCP Socket connection to be automatically closed after use.
+7. Enable the TCP socket connection to be automatically closed after use.
```js
import socket from '@ohos.net.socket'
-// Create a TCPSocket object.
+// Create a TCP socket connection. A TCPSocket object is returned.
let tcp = socket.constructTCPSocketInstance();
-// Subscribe to TCP Socket connection events.
+// Subscribe to events of the TCPSocket object.
tcp.on('message', value => {
console.log("on message")
let buffer = value.message
@@ -139,7 +143,7 @@ tcp.bind(bindAddress, err => {
}
console.log('connect success');
- // Send data.
+ // Send data over the connection.
tcp.send({
data: 'Hello, server!'
}, err => {
@@ -152,7 +156,7 @@ tcp.bind(bindAddress, err => {
});
});
-// Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events.
+// Enable the socket connection to be automatically closed after use. Then, unsubscribe from events of the connection.
setTimeout(() => {
tcp.close((err) => {
console.log('close socket.')
@@ -163,11 +167,92 @@ setTimeout(() => {
}, 30 * 1000);
```
+## Implementing Data Transmission over TCP Socket Server Connections
+
+### How to Develop
+
+The TCP socket server connection process is described as follows:
+
+1. Import the required **socket** module.
+2. Create a TCP socket server connection. A **TCPSocketServer** object is returned.
+3. Bind the local IP address and port, and listen for and accept TCP socket connections established over the socket.
+4. Subscribe to **connect** events of the **TCPSocketServer** object to listen for client connection status changes.
+5. Set up a connection between the client and the server. A **TCPSocketConnection** object is returned.
+6. Subscribe to events of the **TCPSocketConnection** object, and send data to the client through the **TCPSocketConnection** object.
+7. Close the connection between the client and the server.
+8. Unsubscribe from events of the **TCPSocketConnection** and **TCPSocketServer** objects.
+
+```js
+import socket from '@ohos.net.socket'
+
+// Create a TCP socket server connection. A TCPSocketServer object is returned.
+let tcpServer = socket.constructTCPSocketServerInstance();
+
+// Bind the local IP address and port number for listening.
+tcpServer.listen({ address: "192.168.xx.xxx", port: xxxx, family: 1 }, err => {
+ if (err) {
+ console.log("listen fail");
+ return;
+ }
+ console.log("listen success");
+})
+
+// Subscribe to connect events of the TCPSocketServer object.
+tcpServer.on('connect', function(client) {
+ // Subscribe to events of the TCPSocketConnection object.
+ client.on('close', () => {
+ console.log("on close success");
+ });
+ client.on('message', function(value) {
+ let buffer = value.message;
+ let dataView = new DataView(buffer);
+ let str = "";
+ for (let i = 0; i < dataView.byteLength; ++i) {
+ str += String.fromCharCode(dataView.getUint8(i));
+ }
+ console.log("received message--:" + str);
+ console.log("received address--:" + value.remoteInfo.address);
+ console.log("received family--:" + value.remoteInfo.family);
+ console.log("received port--:" + value.remoteInfo.port);
+ console.log("received size--:" + value.remoteInfo.size);
+ });
+
+ // Send data to the client.
+ client.send({data: 'Hello, client!'}, err => {
+ if (err) {
+ console.log('send fail');
+ return;
+ }
+ console.log('send success');
+ });
+
+ // Close the connection between the client and the server.
+ client.close(err => {
+ if (err) {
+ console.log('close fail');
+ return;
+ }
+ console.log('close success');
+ });
+
+ // Unsubscribe from events of the TCPSocketConnection object.
+ setTimeout(() => {
+ client.off('message');
+ client.off('close');
+ }, 10 * 1000);
+});
+
+// Unsubscribe from events of the TCPSocketServer object.
+setTimeout(() => {
+ tcpServer.off('connect');
+}, 30 * 1000);
+```
+
## Implementing Encrypted Data Transmission over TLS Socket Connections
### How to Develop
-TLS Socket connection process on the client:
+The TLSsocket connection process on the client is described as follows:
1. Import the required **socket** module.
@@ -175,21 +260,21 @@ TLS Socket connection process on the client:
3. For two-way authentication, upload the client CA certificate and digital certificate. For one-way authentication, upload the client CA certificate.
-4. Create a **TLSSocket** object.
+4. Create a TLS socket connection. A **TLSsocket** object is returned.
-5. (Optional) Subscribe to TLS Socket connection events.
+5. (Optional) Subscribe to TLS socket connection events.
-6. Send data.
+6. Send data over the connection.
-7. Enable the TLS Socket connection to be automatically closed after use.
+7. Enable the TLS socket connection to be automatically closed after use.
```js
import socket from '@ohos.net.socket'
-// Create a TLS Socket connection (for two-way authentication).
+// Create a TLS socket connection (for two-way authentication). A TLSSocket object is returned.
let tlsTwoWay = socket.constructTLSSocketInstance();
-// Subscribe to TLS Socket connection events.
+// Subscribe to TLS socket connection events.
tlsTwoWay.on('message', value => {
console.log("on message")
let buffer = value.message
@@ -246,7 +331,7 @@ tlsTwoWay.connect(options, (err, data) => {
console.log(data);
});
-// Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events.
+// Enable the socket connection to be automatically closed after use. Then, unsubscribe from events of the connection.
tlsTwoWay.close((err) => {
if (err) {
console.log("close callback error = " + err);
@@ -258,10 +343,10 @@ tlsTwoWay.close((err) => {
tlsTwoWay.off('close');
});
-// Create a TLS Socket connection (for one-way authentication).
+// Create a TLS socket connection (for one-way authentication). A TLSsocket object is returned.
let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication
-// Subscribe to TLS Socket connection events.
+// Subscribe to TLS socket connection events.
tlsTwoWay.on('message', value => {
console.log("on message")
let buffer = value.message
@@ -307,7 +392,7 @@ tlsOneWay.connect(oneWayOptions, (err, data) => {
console.log(data);
});
-// Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events.
+// Enable the socket connection to be automatically closed after use. Then, unsubscribe from events of the connection.
tlsTwoWay.close((err) => {
if (err) {
console.log("close callback error = " + err);
@@ -319,11 +404,3 @@ tlsTwoWay.close((err) => {
tlsTwoWay.off('close');
});
```
-
-## Samples
-
-The following samples are provided to help you better understand how to develop Socket connection features:
-
-- [`Socket`: Socket Connection (ArkTS) (API9)] (https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Socket)
-- [UDP Socket (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/UdpDemoOH)
-- [TCP Socket (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/TcpSocketDemo)
diff --git a/en/application-dev/connectivity/subscribe-remote-state.md b/en/application-dev/connectivity/subscribe-remote-state.md
index 5b21750ba8b56fefcb10a5fff653d7512765c279..d23385e44752cb0945217eddc74117202ca38c5f 100755
--- a/en/application-dev/connectivity/subscribe-remote-state.md
+++ b/en/application-dev/connectivity/subscribe-remote-state.md
@@ -1,5 +1,7 @@
# 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
diff --git a/en/application-dev/connectivity/websocket-connection.md b/en/application-dev/connectivity/websocket-connection.md
index 4c373011c45be18183e4c622c3e7e35b97198a24..1b162256db5cad28aa50ca6989625f9191fb2257 100644
--- a/en/application-dev/connectivity/websocket-connection.md
+++ b/en/application-dev/connectivity/websocket-connection.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/database/Readme-EN.md b/en/application-dev/database/Readme-EN.md
index 77e1d8f9738d949ce9b0f0396bf66f99b9bf924e..74a44f63945d867ff76bb783e2ef0a6feb35861c 100644
--- a/en/application-dev/database/Readme-EN.md
+++ b/en/application-dev/database/Readme-EN.md
@@ -16,7 +16,11 @@
- [Database Backup and Restoration](data-backup-and-restore.md)
- [Database Encryption](data-encryption.md)
- [Access Control by Device and Data Level](access-control-by-device-and-data-level.md)
-- Cross-Application Data Sharing (for System Applications Only)
- - [Cross-Application Data Sharing Overview](share-device-data-across-apps-overview.md)
- - [Sharing Data Using DataShareExtensionAbility](share-data-by-datashareextensionability.md)
- - [Sharing Data in Silent Access](share-data-by-silent-access.md)
+- Cross-Application Data Sharing
+ - [Data Sharing Overview](data-share-overview.md)
+ - [Unified Data Definition](unified-data-definition.md)
+ - One-to-Many Data Sharing (for System Applications Only)
+ - [Sharing Data Using DataShareExtensionAbility](share-data-by-datashareextensionability.md)
+ - [Silent Access via the DatamgrService](share-data-by-silent-access.md)
+ - Many-to-Many Data Sharing
+ - [Sharing Data Using Unified Data Channels](unified-data-channels.md)
\ No newline at end of file
diff --git a/en/application-dev/database/data-mgmt-overview.md b/en/application-dev/database/data-mgmt-overview.md
index aa98d97da5acdce3a382a70d383e140463a5399a..e6b77c1d89c5cc31e6e1fb9db05e7ab8d2607a7e 100644
--- a/en/application-dev/database/data-mgmt-overview.md
+++ b/en/application-dev/database/data-mgmt-overview.md
@@ -3,7 +3,7 @@
## Function
-Data management provides data storage, management, and synchronization capabilities. For example, you can store the Contacts application data in database for secure management and shared access, and synchronize the contacts information with a smart watch.
+Data management provides data storage, management, and synchronization capabilities. For example, you can store the Contacts application data in database for secure management and shared access, and synchronize the Contacts information with a smart watch.
- Data storage: provides data persistence capabilities, which can be classified into user preferences, key-value (KV) stores, and relational database (RDB) stores by data characteristics.
@@ -16,9 +16,9 @@ The database stores created by an application are saved to the application sandb
## Working Principles
-The data management module includes user preferences (**Preferences**), KV data management (**KV-Store**), RDB data management (**RelationalStore**), distributed data object (**DataObject**), and cross-application data management (**DataShare**). The interface layer provides standard JavaScript APIs for application development. The Frameworks&System service layer implements storage and synchronization of component data, and provides dependencies for SQLite and other subsystems.
+The data management module includes preferences, KV data management (KV-Store), relational data management (RelatoinalStore), distributed data object (DataObject), cross-application data management (DataShare), and unified data management framework (UDMF). The interface layer provides standard JavaScript APIs for application development. The Frameworks&System service layer implements storage and synchronization of component data, and provides dependencies for SQLite and other subsystems.
- **Figure 1** Data management architecture
+**Figure 1** Data management architecture

@@ -33,4 +33,7 @@ The data management module includes user preferences (**Preferences**), KV data
- **DataShare**: provides the data provider-consumer mode to implement addition, deletion, modification, and query of cross-application data on a device, and notification subscription. **DataShare** is not bound to any database and can interact with RDB and KV stores. You can also encapsulate your own databases for C/C++ applications. In addition to the provider-consumer mode, **DataShare** provides silent access, which allows direct access to the provider's data via the DatamgrService proxy instead of starting the provider. Currently, only the RDB stores support silent access.
+- **UDMF**: defines the data language and standards for cross-application and cross-device data interaction, improving data interaction efficiency. The UDMF provides secure and standard data transmission channels and supports different levels of data access permissions and lifecycle management policies. It helps implement efficient data sharing across applications and devices.
+
- **DatamgrService**: implements synchronization and cross-application sharing for other components, including cross-device synchronization of **RelationalStore** and **KV-Store**, silent access to provider data of **DataShare**, and temporary storage of **DataObject** synchronization object data.
+
diff --git a/en/application-dev/database/data-persistence-by-preferences.md b/en/application-dev/database/data-persistence-by-preferences.md
index e37c12369d59d2165220c8d8f5bbaa85029c37df..553050a55a585dc34e620623eb187a0365b8488e 100644
--- a/en/application-dev/database/data-persistence-by-preferences.md
+++ b/en/application-dev/database/data-persistence-by-preferences.md
@@ -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
diff --git a/en/application-dev/database/data-persistence-by-rdb-store.md b/en/application-dev/database/data-persistence-by-rdb-store.md
index f2bb5e2d4098bbb19b3c791ed61307ffd78f0ec3..5879f73dac606c956fa305e9602eb1673f1fb369 100644
--- a/en/application-dev/database/data-persistence-by-rdb-store.md
+++ b/en/application-dev/database/data-persistence-by-rdb-store.md
@@ -18,7 +18,7 @@ A relational database (RDB) store is used to store data in complex relational mo
**RelationalStore** provides APIs for applications to perform data operations. With SQLite as the underlying persistent storage engine, **RelationalStore** provides SQLite database features, including transactions, indexes, views, triggers, foreign keys, parameterized queries, prepared SQL statements, and more.
**Figure 1** Working mechanism
-
+

@@ -37,23 +37,23 @@ A relational database (RDB) store is used to store data in complex relational mo
The following table lists the APIs used for RDB data persistence. Most of the APIs are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [RDB Store](../reference/apis/js-apis-data-relationalStore.md).
-| API| Description|
+| API| Description|
| -------- | -------- |
-| getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void | Obtains a **RdbStore** instance to implement RDB store operations. You can set **RdbStore** parameters based on actual requirements and use **RdbStore** APIs to perform data operations.|
-| executeSql(sql: string, bindArgs: Array<ValueType>, callback: AsyncCallback<void>):void | Executes an SQL statement that contains specified arguments but returns no value.|
-| insert(table: string, values: ValuesBucket, callback: AsyncCallback<number>):void | Inserts a row of data into a table.|
-| update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback<number>):void | Updates data in the RDB store based on the specified **RdbPredicates** instance.|
-| delete(predicates: RdbPredicates, callback: AsyncCallback<number>):void | Deletes data from the RDB store based on the specified **RdbPredicates** instance.|
-| query(predicates: RdbPredicates, columns: Array<string>, callback: AsyncCallback<ResultSet>):void | Queries data in the RDB store based on specified conditions.|
-| deleteRdbStore(context: Context, name: string, callback: AsyncCallback<void>): void | Deletes an RDB store.|
+| getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void | Obtains a **RdbStore** instance to implement RDB store operations. You can set **RdbStore** parameters based on actual requirements and use **RdbStore** APIs to perform data operations.|
+| executeSql(sql: string, bindArgs: Array<ValueType>, callback: AsyncCallback<void>):void | Executes an SQL statement that contains specified arguments but returns no value.|
+| insert(table: string, values: ValuesBucket, callback: AsyncCallback<number>):void | Inserts a row of data into a table.|
+| update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback<number>):void | Updates data in the RDB store based on the specified **RdbPredicates** instance.|
+| delete(predicates: RdbPredicates, callback: AsyncCallback<number>):void | Deletes data from the RDB store based on the specified **RdbPredicates** instance.|
+| query(predicates: RdbPredicates, columns: Array<string>, callback: AsyncCallback<ResultSet>):void | Queries data in the RDB store based on specified conditions.|
+| deleteRdbStore(context: Context, name: string, callback: AsyncCallback<void>): void | Deletes an RDB store.|
## How to Develop
-1. Obtain an **RdbStore** instance. Example:
+1. Obtain an **RdbStore** instance. Example:
Stage model:
-
+
```js
import relationalStore from '@ohos.data.relationalStore'; // Import the module.
import UIAbility from '@ohos.app.ability.UIAbility';
@@ -65,7 +65,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
securityLevel: relationalStore.SecurityLevel.S1 // Database security level.
};
- // The current RDB store version is 3, and the table structure is EMPLOYEE (NAME, AGE, SALARY, CODES).
+ // The RDB store version is 3, and the table structure is EMPLOYEE (NAME, AGE, SALARY, CODES).
const SQL_CREATE_TABLE ='CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)'; // SQL statement for creating a data table.
relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => {
@@ -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.
});
}
@@ -106,7 +106,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
FA model:
-
+
```js
import relationalStore from '@ohos.data.relationalStore'; // Import the module.
import featureAbility from '@ohos.ability.featureAbility';
@@ -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.
});
```
@@ -160,10 +160,12 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
>
> - The RDB store created by an application varies with the context. Multiple RDB stores are created for the same database name with different application contexts. For example, each UIAbility has its own context.
>
- > - When an application calls **getRdbStore()** to obtain an RDB store instance for the first time, the corresponding database file is generated in the application sandbox. If you want to move the files of an RDB store to another place for view, you must also move the temporary files with finename extensions **-wal** or **-shm** in the same directory. Once an application is uninstalled, the database files and temporary files generated by the application on the device are also removed.
+ > - When an application calls **getRdbStore()** to obtain an RDB store instance for the first time, the corresponding database file is generated in the application sandbox. When the RDB store is used, temporary files ended with **-wal** and **-shm** may be generated in the same directory as the database file. If you want to move the database files to other places, you must also move these temporary files. After the application is uninstalled, the database files and temporary files generated on the device are also removed.
-2. Use **insert()** to insert data to the RDB store. Example:
-
+2. Use **insert()** to insert data to the RDB store.
+
+ Example:
+
```js
const valueBucket = {
'NAME': 'Lisa',
@@ -177,13 +179,13 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
return;
}
console.info(`Succeeded in inserting data. rowId:${rowId}`);
- })
+})
```
-
+
> **NOTE**
- >
+>
> **RelationalStore** does not provide explicit flush operations for data persistence. Data inserted by **insert()** is stored in files persistently.
-
+
3. Modify or delete data based on the specified **Predicates** instance.
Use **update()** to modify data and **delete()** to delete data.
@@ -258,9 +260,13 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
Example:
+ > **NOTE**
+ >
+ > After the deletion, you are advised to set the database object to null.
+
Stage model:
-
+
```js
import UIAbility from '@ohos.app.ability.UIAbility';
@@ -271,6 +277,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
+ store = null;
console.info('Succeeded in deleting RdbStore.');
});
}
@@ -279,7 +286,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
FA model:
-
+
```js
import featureAbility from '@ohos.ability.featureAbility';
@@ -291,6 +298,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
+ store = null;
console.info('Succeeded in deleting RdbStore.');
});
- ```
+ ```
\ No newline at end of file
diff --git a/en/application-dev/database/data-share-overview.md b/en/application-dev/database/data-share-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a163dcc56a5592038cd497bddafa572a90628f7
--- /dev/null
+++ b/en/application-dev/database/data-share-overview.md
@@ -0,0 +1,71 @@
+# Cross-Application Data Sharing
+
+## Introduction
+
+OpenHarmony provides APIs for an application to manage its own data and share data with other applications.
+
+Data needs to be shared in a wealth of scenarios. For example, the Contacts, short message service (SMS), and Gallery data always needs to be shared with other applications. However, certain data, such as accounts and passwords, cannot be shared. Some data, such as SMS messages, can be queried but not modified by other applications. Therefore, a secure and efficient cross-application data sharing mechanism for different data sharing scenarios and data privacy protection is very important.
+
+Currently, OpenHarmony supports one-to-many and many-to-many cross-application data sharing, based on the number of the data provider applications involved.
+
+## Basic Concepts
+
+Before you start, understand the following concepts:
+
+- **Data provider**: an application that provides data and implements related services. It is also called the producer or server.
+
+- **Data consumer**: an application that accesses the data or services provided by the data provider. It is also called the client.
+
+- **ValuesBucket**: a set of data to be inserted. It can be one or more data records in key-value (KV) pairs. In each KV pair, the key must be of the string type, and the value can be a number, a string, a Boolean value, or an unsigned integer array.
+
+- **ResultSet**: a set of query results. It provides flexible modes for users to obtain various data.
+
+- **Predicates**: an object that specifies the conditions for updating, deleting, or querying data in a database.
+
+## Unified Data Definition
+
+When data needs to be shared among multiple applications, a large amount of data needs to be converted for data interaction because the data definition and format vary with applications. To reduce application/service data interaction costs, OpenHarmony uses the unified data definition as the unified data language to build cross-application data interaction standards.
+
+The unified data definition defines common data types. Applications can use the APIs provided by the Unified Data Management Framework (UDMF) to create and use these data types. For details, see [Unified Data Definition](unified-data-definition.md).
+
+## One-to-Many Cross-Application Data Sharing
+
+You can use **DataShare** to implement one-to-many data sharing across applications. Two implementation modes are provided, depending on whether the data provider is started in the cross-application data sharing.
+
+### Implementation
+
+The data provider can directly use **DataShare** to share data with other applications without complex encapsulation. The data consumer only needs to use a set of APIs because the **DataShare** access mode does not vary with the data provision mode. This greatly reduces the learning time and development difficulty.
+
+**DataShare** implements cross-application data sharing in either of the following ways:
+
+- [Using DataShareExtensionAbility](share-data-by-datashareextensionability.md)
+
+ You need to implement an ExtensionAbility with callbacks in the HAP. When the data consumer calls an API, the ExtensionAbility of the data provider will be automatically started to invoke the registered callback.
+
+ You can use **DataShareExtensionAbility** when the cross-application data access involves service operations other than mere addition, deletion, modification, and query of data in databases.
+
+- [Using Silent Access via the DatamgrService](share-data-by-silent-access.md)
+
+ You need to configure database access rules in the HAP. When the data consumer calls an API, the system ability automatically obtains the access rules in the HAP and returns data without starting the data provider.
+
+ You can use this mode when the cross-application data access involves only database operations (data addition, deletion, modification, and query) or data hosted to the DatamgrService.
+
+If your application is signed with a system signature, you can use both methods. When data is created for the first time, use **DataShareExtensionAbility**. When data is accessed and modified later, use the **DatamgrService** to share data. That is, the data provider is started only when the data is accessed for the first time.
+
+### Restrictions
+
+- **DataShare** is subject to the limitations on the database used by the data provider. For example, the supported data models, length of the keys and values, and maximum number of databases that can be accessed at a time by each application vary with the database in use.
+
+- The payloads of **ValuesBucket**, **Predicates**, and **ResultSet** are restricted by IPC.
+
+- Currently, **dataShare** supports development based on the stage model only.
+
+## Many-to-Many Cross-Application Data Sharing
+
+In one-to-many cross-application data sharing, there is only one data provider. In many-to-many cross-application data sharing, you need to consider data definition, data exchange, and permission management. The UDMF provides a new data sharing and interaction mode to implement many-to-many cross-application data sharing.
+
+### Implementation
+
+[Sharing Data via Unified Data Channels](unified-data-channels.md)
+
+Applications can call the APIs provided by the UDMF to write data that complies with the unified data definition to different data sharing channels of the UDMF. The data in these channels can be read by other applications. The data written into the UDMF is managed based on the permissions of the application, permissions of the data channels, and the permission management logic of the UDMF. Lifecycle management is also performed on the data written into the channels in the same way. In this way, the data scattered in each application is aggregated via different channels of the UDMF, improving the development efficiency and data experience of users.
diff --git a/en/application-dev/database/data-sync-of-kv-store.md b/en/application-dev/database/data-sync-of-kv-store.md
index eb8994570f04b0d6690c2b91b1b1745602e980fb..b23dd91ed1a7b4ea0cd13f6d9b49de82e1821190 100644
--- a/en/application-dev/database/data-sync-of-kv-store.md
+++ b/en/application-dev/database/data-sync-of-kv-store.md
@@ -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
diff --git a/en/application-dev/database/figures/dataManagement.jpg b/en/application-dev/database/figures/dataManagement.jpg
index a43ca576222ad1da550242ed34c5f82700d52392..6555d34202927dc202fcb0ab233bc42740f39dbe 100644
Binary files a/en/application-dev/database/figures/dataManagement.jpg and b/en/application-dev/database/figures/dataManagement.jpg differ
diff --git a/en/application-dev/database/figures/udmf_type_ADT.png b/en/application-dev/database/figures/udmf_type_ADT.png
new file mode 100644
index 0000000000000000000000000000000000000000..2eb1e7b94080b6d611b1ed7abaceda31b04442e7
Binary files /dev/null and b/en/application-dev/database/figures/udmf_type_ADT.png differ
diff --git a/en/application-dev/database/figures/udmf_type_File.png b/en/application-dev/database/figures/udmf_type_File.png
new file mode 100644
index 0000000000000000000000000000000000000000..80bbec073de7e4e75da239a8a073453545260cc1
Binary files /dev/null and b/en/application-dev/database/figures/udmf_type_File.png differ
diff --git a/en/application-dev/database/figures/udmf_type_SDT.png b/en/application-dev/database/figures/udmf_type_SDT.png
new file mode 100644
index 0000000000000000000000000000000000000000..026ce5bd7ae68f4dbabdcf5bac63e721454e17f5
Binary files /dev/null and b/en/application-dev/database/figures/udmf_type_SDT.png differ
diff --git a/en/application-dev/database/figures/udmf_type_Text.png b/en/application-dev/database/figures/udmf_type_Text.png
new file mode 100644
index 0000000000000000000000000000000000000000..d12a2390dce2d08417e7024d15ee431dde66756b
Binary files /dev/null and b/en/application-dev/database/figures/udmf_type_Text.png differ
diff --git a/en/application-dev/database/share-data-by-datashareextensionability.md b/en/application-dev/database/share-data-by-datashareextensionability.md
index 7f70ab30d4c04c421c1e18032a0da13e590f80a7..d3c28e31c20f0aa3d6720359aa28e84af2061a63 100644
--- a/en/application-dev/database/share-data-by-datashareextensionability.md
+++ b/en/application-dev/database/share-data-by-datashareextensionability.md
@@ -16,8 +16,7 @@ There are two roles in **DataShare**:
- Data consumer: accesses the data provided by the provider using [createDataShareHelper()](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper).
-**Figure 1** Data sharing mechanism
-
+**Figure 1** Data sharing mechanism

- The **DataShareExtensionAbility** module, as the data provider, implements services related to data sharing between applications.
@@ -32,7 +31,7 @@ There are two roles in **DataShare**:
## How to Develop
-### Data Provider Application Development (Only for System Applications)
+### Data Provider Application (Only for System Applications)
[DataShareExtensionAbility](../reference/apis/js-apis-application-dataShareExtensionAbility.md) provides the following APIs. You can override these APIs as required.
@@ -146,7 +145,7 @@ override the service implementation as required. For example, if the data provid
"icon": "$media:icon",
"description": "$string:description_datashareextability",
"type": "dataShare",
- "uri": "datashare://com.samples.datasharetest.DataShare",
+ "uri": "datashareproxy://com.samples.datasharetest.DataShare",
"exported": true,
"metadata": [{"name": "ohos.extension.dataShare", "resource": "$profile:data_share_config"}]
}
@@ -155,11 +154,11 @@ override the service implementation as required. For example, if the data provid
**Table 2** Fields in the data_share_config.json file
- | Field| Description | Mandatory|
- | ------------ | ------------------------------------------------------------ | --- |
- | tableConfig | Label configuration.| Yes|
- | uri | Range for which the configuration takes effect. The URI supports the following formats in descending order by priority: 1. *****: indicates all databases and tables. 2. **datashare:///{*bundleName*}/{*moduleName*}/{*storeName*}**: specifies a database. 3. **datashare:///{*bundleName*}/{*moduleName*}/{*storeName*}/{*tableName*}**: specifies a table. If URIs of different formats are configured, only the URI with higher priority takes effect. | Yes|
- | crossUserMode | Whether data is shared by multiple users. The value **1** means to share data between multiple users, and the value **2** means the opposite. | Yes|
+ | Field | Description | Mandatory |
+ | ------------- | ---------------------------------------- | ---- |
+ | tableConfig | Label configuration. | Yes |
+ | uri | Range for which the configuration takes effect. The URI supports the following formats in descending order by priority: - *****: indicates all databases and tables. - **datashareproxy://{bundleName}/{moduleName}/{storeName}**: specifies a database. - **datashareproxy://{bundleName}/{moduleName}/{storeName}/{tableName}**: specifies a table. | Yes |
+ | crossUserMode | Whether data is shared by multiple users. The value **1** means to share data between multiple users, and the value **2** means the opposite. | Yes |
**data_share_config.json Example**
@@ -170,18 +169,18 @@ override the service implementation as required. For example, if the data provid
"crossUserMode": 1
},
{
- "uri": "datashare:///com.acts.datasharetest/entry/DB00",
+ "uri": "datashareproxy://com.acts.datasharetest/entry/DB00",
"crossUserMode": 1
},
{
- "uri": "datashare:///com.acts.datasharetest/entry/DB00/TBL00",
+ "uri": "datashareproxy://com.acts.datasharetest/entry/DB00/TBL00",
"crossUserMode": 2
}
]
```
-### Data Consumer Application Development
+### Data Consumer Application
1. Import the dependencies.
@@ -195,7 +194,7 @@ override the service implementation as required. For example, if the data provid
```js
// Different from the URI defined in the module.json5 file, the URI passed in the parameter has an extra slash (/), because there is a DeviceID parameter between the second and the third slash (/).
- let dseUri = ('datashare:///com.samples.datasharetest.DataShare');
+ let dseUri = ('datashareproxy://com.samples.datasharetest.DataShare');
```
3. Create a **DataShareHelper** instance.
@@ -239,3 +238,4 @@ override the service implementation as required. For example, if the data provid
console.info(`dsHelper delete result:${data}`);
});
```
+
diff --git a/en/application-dev/database/share-data-by-silent-access.md b/en/application-dev/database/share-data-by-silent-access.md
index 50ff03f084c889a807c6caf4d7c369bfbe0d2a51..046d78b9eac73717cd16b4218f108c1a7979e54f 100644
--- a/en/application-dev/database/share-data-by-silent-access.md
+++ b/en/application-dev/database/share-data-by-silent-access.md
@@ -1,19 +1,40 @@
-# Data Sharing Through Silent Access
+# Silent Access via the DatamgrService
## When to Use
-In a typical cross-application data access scenario, an application may be started multiple times.
+In a typical cross-application data access scenario, the data provider may be started multiple times.
-To reduce the number of application startup times and improve the access speed, OpenHarmony provides the silent access feature, which allows direct access to the database without starting the data provider.
+To reduce the number of startup times of the data provider and improve the access speed, OpenHarmony provides the silent access feature, which allows access to the database without starting the data provider.
-Silent access supports only basic database access. If service processing is required, implement service processing in the data consumer.
+In silent data access, the DatamgrService accesses and modifies data without starting the data provider.
-If the service processing is complex, use **DataShareExtensionAbility** to start the data provider.
+The DatamgrService supports basic database access or data hosting only. If service processing is required, the service processing needs to be encapsulated into APIs for the data consumer to call.
+
+If the service processing is too complex to be processed by the data consumer, use **DataShareExtensionAbility** to start the data provider.
## Working Principles
+The DatamgrService can serve as a proxy to access the following types of data:
+
+- Persistent data
+
+ Persistent data belongs to the database of the data provider. It is stored in the sandbox of the data provider and can be shared in declaration mode by the data provider. Persistent data is configured as data tables for access.
+
+
+- Process data
+
+ The process data managed by the **DatamgrService** is stored in the DatamgrService sandbox in JSON or byte format. This type of data is automatically deleted 10 days after no subscription.
+
+
+| Type | Storage Location | Data Format | Validity Period | Application Scenario |
+| ----- | --------- | ----------- | ------------ | --------------------------------- |
+| Persistent data| Sandbox of the data provider | Tables in the database | Permanent storage | RDB data applications, such as schedules and conferences. |
+| Process data | DatamgrService sandbox| JSON or byte| Automatically deleted 10 days after no subscription| Applications featuring simple and time-sensitive data, such as step count, weather, and heart rate.|
+
+
+
**Figure 1** Silent access

@@ -21,26 +42,271 @@ If the service processing is complex, use **DataShareExtensionAbility** to start
- In silent access, **DatamgrService** obtains the access rules configured by the data provider through directory mapping, performs preprocessing based on rules, and accesses the database.
- To use silent access, the URIs must be in the following format:
- datashare:///{bundleName}/{moduleName}/{storeName}/{tableName}?Proxy=true
+
+datashareproxy://{bundleName}/{dataPath}
+
+The **DatamgrService** obtains the data provider application based on **bundleName**, reads the configuration, verifies the permission, and accesses data.
+
+ **dataPath** identifies the data. It can be customized and must be unique in the same data provider application.
+
- "Proxy=true" means to access data without starting the data provider. If **Proxy** is not set to **true**, the data provider is started.
+## Constraints
- The **DatamgrService** obtains the data provider application based on **bundleName**, reads the configuration, verifies the permission, and accesses data.
+- Currently, only the RDB stores support silent data access.
+- The system supports a maximum of 16 concurrent query operations. Excess query requests need to be queued for processing.
+- The proxy is not allowed to create a database for persistent data. To create a database, you must start the data provider.
+- If the data provider is an application with a normal signature, the data read/write permission must be system_basic or higher.
-## Constraints
+## Available APIs
-- Currently, only RDB stores support silent access.
+The following table lists the APIs for silent data access. Most of the APIs are executed asynchronously in callback or promise mode. In the following table, callback-based APIs are used as an example. For more information about the APIs, see [Data Sharing](../reference/apis/js-apis-data-dataShare.md).
-- The system supports a maximum of 16 concurrent query operations. Excess query requests need to be queued for processing.
+### Common API
+
+| API | Description |
+| ---------------------------------------- | -------------------- |
+| createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback<DataShareHelper>): void | Creates a **DataShareHelper** instance.|
+
+### APIs for Persistent Data
+
+| API | Description |
+| ---------------------------------------- | -------------------- |
+| insert(uri: string, value: ValuesBucket, callback: AsyncCallback<number>): void | Inserts a row of data into a table. |
+| delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback<number>): void | Deletes one or more data records from the database. |
+| query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: AsyncCallback<DataShareResultSet>): void | Queries data in the database. |
+| update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback<number>): void | Updates data in the database. |
+| addTemplate(uri: string, subscriberId: string, template: Template): void | Adds a data template with the specified subscriber. |
+| on(type: 'rdbDataChange', uris: Array<string>, templateId: TemplateId, callback: AsyncCallback<RdbDataChangeNode>): Array<OperationResult | Subscribes to the changes of the data corresponding to the specified URI and template.|
+
+### APIs for Process Data
+
+| API | Description |
+| ---------------------------------------- | ------------------ |
+| publish(data: Array<PublishedItem>, bundleName: string, version: number, callback: AsyncCallback<Array<OperationResult>>): void | Publish data to the **DatamgrService**.|
+| on(type: 'publishedDataChange', uris: Array<string>, subscriberId: string, callback: AsyncCallback<PublishedDataChangeNode>): Array<OperationResult> | Subscribes to changes of the published data. |
+
+
+
+## Implementation of the Persistence Data
+
+The following describes how to share an RDB store.
+
+### Data Provider Application
+
+1. In the **module.json5** file, set the ID, read/write permissions, and basic information of the table to be shared under **proxyDatas**.
+
+ **Table 1** Fields of proxyDatas in module.json5
+
+ | Field | Description | Mandatory |
+ | ----------------------- | ---------------------------------------- | ---- |
+ | uri | URI of the data, which is the unique identifier for cross-application data access. | Yes |
+ | requiredReadPermission | Permission required for reading data from the data proxy. If this parameter is not set, other applications are not allowed to access data. For details about the supported permissions, see [Application Permission List](../security/permission-list.md). | No |
+ | requiredWritePermission | Permission required for modifying data from the data proxy. If this parameter is not set, other applications are not allowed to modify the data. For details about the supported permissions, see [Application Permission List](../security/permission-list.md). | No |
+ | metadata | Data source information, including the **name** and **resource** fields. The **name** field identifies the configuration, which has a fixed value of **dataProperties**. The value of **resource** is **$profile:{fileName}**, indicating that the name of the configuration file is **{fileName}.json**.| Yes |
+
+ **module.json5 example**
+
+ ```json
+ "proxyDatas":[
+ {
+ "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test",
+ "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
+ "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING",
+ "metadata": {
+ "name": "dataProperties",
+ "resource": "$profile:my_config"
+ }
+ }
+ ]
+ ```
+ **Table 2** Fields in my_config.json
+
+ | Field | Description | Mandatory |
+ | ----- | ---------------------------------------- | ---- |
+ | path | Data source path, in the **Database_name/Table_name** format. Currently, only RDB stores are supported. | Yes |
+ | type | Database type. Currently, only **rdb** is supported. | Yes |
+ | scope | Scope of the database. - **module** indicates that the database is located in this module. - **application** indicates that the database is located in this application.| No |
+
+ **my_config.json example**
+
+ ```json
+ {
+ "path": "DB00/TBL00",
+ "type": "rdb",
+ "scope": "application"
+ }
+ ```
+
+### Data Consumer Application
+
+
+1. Import dependencies.
+
+ ```js
+ import dataShare from '@ohos.data.dataShare';
+ import dataSharePredicates from '@ohos.data.dataSharePredicates';
+ ```
+
+2. Define the URI string for communicating with the data provider.
+
+ ```js
+ let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/test');
+ ```
+
+3. Create a **DataShareHelper** instance.
+
+ ```js
+ let dsHelper;
+ let abilityContext;
+
+ export default class EntryAbility extends UIAbility {
+ onWindowStageCreate(windowStage) {
+ abilityContext = this.context;
+ dataShare.createDataShareHelper(abilityContext, "", {
+ isProxy: true
+ }, (err, data) => {
+ dsHelper = data;
+ });
+ }
+ }
+ ```
+
+4. Use the APIs provided by **DataShareHelper** to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
+
+ ```js
+ // Construct a piece of data.
+ let valuesBucket = {
+ 'name': 'ZhangSan', 'age': 21, 'isStudent': false, 'Binary': new Uint8Array([1, 2, 3])
+ };
+ let updateBucket = {
+ 'name': 'LiSi', 'age': 18, 'isStudent': true, 'Binary': new Uint8Array([1, 2, 3])
+ };
+ let predicates = new dataSharePredicates.DataSharePredicates();
+ let valArray = ['*'];
+ // Insert a piece of data.
+ dsHelper.insert(dseUri, valuesBucket, (err, data) => {
+ console.info(`dsHelper insert result:${data}`);
+ });
+ // Update data.
+ dsHelper.update(dseUri, predicates, updateBucket, (err, data) => {
+ console.info(`dsHelper update result:${data}`);
+ });
+ // Query data.
+ dsHelper.query(dseUri, predicates, valArray, (err, data) => {
+ console.info(`dsHelper query result:${data}`);
+ });
+ // Delete data.
+ dsHelper.delete(dseUri, predicates, (err, data) => {
+ console.info(`dsHelper delete result:${data}`);
+ });
+ ```
+
+5. Subscribe to the specified data.
+
+ ```js
+ function onCallback(err, node: dataShare.RdbDataChangeNode) {
+ console.info("uri " + JSON.stringify(node.uri));
+ console.info("templateId " + JSON.stringify(node.templateId));
+ console.info("data length " + node.data.length);
+ for (let i = 0; i < node.data.length; i++) {
+ console.info("data " + node.data[i]);
+ }
+ }
+
+ let template = {
+ predicates: {
+ "p1": "select * from TBL00",
+ "p2": "select name from TBL00",
+ },
+ scheduler: ""
+ }
+ dsProxyHelper.addTemplate(dseUri, "111", template);
+ let templateId: dataShare.TemplateId = {
+ subscriberId: "111",
+ bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient"
+ }
+ // When the DatamgrService modifies data, onCallback is invoked to return the data queried based on the rules in the template.
+ let result: Array = dsProxyHelper.on("rdbDataChange", [dseUri], templateId, onCallback);
+ ```
+
+## Implementation of the Process Data
+
+The following describes how to host process data.
+
+### (Optional) Data Provider Application
+
+In the **module.json5** file of the data provider, set the process data ID, read/write permissions, and basic information under **proxyDatas**.
+
+> **NOTE**
+>
+> - This step is optional.
+> - If **proxyDatas** is not configured, the hosted data cannot be accessed by other applications.
+> - If **proxyDatas** is not configured, you do not need to use the full data path. For example, you can use **weather** instead of **datashareproxy://com.acts.ohos.data.datasharetest/weather** when publishing, subscribing to, and querying data.
+
+**Table 3** Fields of proxyDatas in module.json5
+
+| Field | Description | Mandatory |
+| ----------------------- | ----------------------------- | ---- |
+| uri | URI of the data, which is the unique identifier for cross-application data access. | Yes |
+| requiredReadPermission | Permission required for reading data from the data proxy. If this parameter is not set, other applications are not allowed to access data. For details about the supported permissions, see [Application Permission List](../security/permission-list.md).| No |
+| requiredWritePermission | Permission required for modifying data from the data proxy. If this parameter is not set, other applications are not allowed to access data. For details about the supported permissions, see [Application Permission List](../security/permission-list.md).| No |
+
+**module.json5 example**
+
+```json
+"proxyDatas": [
+ {
+ "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather",
+ "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
+ "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING"
+ }
+]
+```
+
+### Data Consumer Application
+
+1. Import dependencies.
+
+ ```js
+ import dataShare from '@ohos.data.dataShare';
+ ```
+
+2. Create a **DataShareHelper** instance.
+
+ ```js
+ let dsHelper;
+ let abilityContext;
-- A proxy cannot be used to create a database. If a database needs to be created, the data provider must be started.
+ export default class EntryAbility extends UIAbility {
+ onWindowStageCreate(windowStage) {
+ abilityContext = this.context;
+ dataShare.createDataShareHelper(abilityContext, "", {isProxy : true}, (err, data) => {
+ dsHelper = data;
+ });
+ }
+ }
+ ```
+3. Use the APIs provided by **DataShareHelper** to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
-## How to Develop
+ ```js
+ // Construct two pieces of data. The first data is not configured with proxyDatas and cannot be accessed by other applications.
+ let data : Array = [
+ {key:"city", subscriberId:"11", data:"xian"},
+ {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}];
+ // Publish data.
+ let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetestclient");
+ ```
-The URI must be in the following format:
+4. Subscribe to the specified data.
-datashare:///{bundleName}/{moduleName}/{storeName}/{tableName}?Proxy=true
+ ```js
+ function onPublishCallback(err, node:dataShare.PublishedDataChangeNode) {
+ console.info("onPublishCallback");
+ }
+ let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"];
+ let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback);
+ ```
-For details about the development procedure and implementation, see [Sharing Data Using DataShareExtensionAbility](share-data-by-datashareextensionability.md).
+
diff --git a/en/application-dev/database/sync-app-data-across-devices-overview.md b/en/application-dev/database/sync-app-data-across-devices-overview.md
index c2f6361786325ccd753aa8fa4afa3446d37b6e89..4a3543a44c2b9e6e7fa9a4248010254c6ce1b035 100644
--- a/en/application-dev/database/sync-app-data-across-devices-overview.md
+++ b/en/application-dev/database/sync-app-data-across-devices-overview.md
@@ -7,7 +7,7 @@ The distributed application data synchronization allows the data of an applicati
For example, when data is added, deleted, or modified for an application on a device, the same application on another device can obtain the updated data. You can use this feature in the distributed Gallery, Notepad, Contacts, and File Manager.
-For details about how to subscribe to database change notifications between different applications, see [Sharing Application Data with Other Applications](share-device-data-across-apps-overview.md).
+For details about how to subscribe to database change notifications between different applications, see [Cross-Application Data Sharing](data-share-overview.md).
The data storage modes vary depending on the lifecycle of data to be synchronized:
@@ -24,7 +24,7 @@ In a distributed scenario, cross-device collaboration demands consistent data be
The data consistency can be classified into the following types:
-- Strong consistency: When data is inserted, deleted, or modified on a device, other devices in the same network can obtain the updates eventually, but may not immediately.
+- Strong consistency: When data is inserted, deleted, or modified on a device, other devices in the same network will obtain the latest data immediately. Once data is modified, the devices can read the updated data eventually, but may not read the updated data immediately.
- Weak consistency: When data is added, deleted, or modified on a device, other devices in the same network may or may not obtain the updates. The data on these devices may be inconsistent after a certain period of time.
diff --git a/en/application-dev/database/unified-data-channels.md b/en/application-dev/database/unified-data-channels.md
new file mode 100644
index 0000000000000000000000000000000000000000..b31b9532eafb700da67c2dbcc5464f8f58867d23
--- /dev/null
+++ b/en/application-dev/database/unified-data-channels.md
@@ -0,0 +1,165 @@
+# Sharing Data via Unified Data Channels
+
+
+## When to Use
+
+In many-to-many data sharing across applications, a data channel needs to be provided to access data of different applications and share the data with other applications.
+
+The Unified Data Management Framework (UDMF) provides unified data channels and standard data access interfaces for different service scenarios of many-to-many cross-application data sharing.
+
+## Definition and Implementation of Unified Data Channels
+
+The unified data channel provides cross-application data access for various service scenarios. It can temporarily store the unified data objects to be shared by an application, and manage the access permissions and lifecycle of the data according to certain policies.
+
+The unified data channel is implemented by the system ability provided by the UDMF. When an application (data provider) needs to share data, it calls the **insert()** method provided by the UDMF to write the data to the UDMF data channel, and calls UDMF **update()** or **delete()** to update or delete the data. After passing the permission verification, the target application (data consumer) calls the UDMF **read()** to access the data. After the data is read, the UDMF performs lifecycle management of the data.
+
+The unified data object (**UnifiedData**) is uniquely identified by a URI in the UDMF data channel. The URI is in the **udmf://*intention*/*bundleName*/*groupId*** format, where:
+
++ **udmf**: protocol used to provide the data channel.
+
++ *intention*: an enum of the data channel types supported by the UDMF.
+
++ *bundleName*: bundle name of the data source application.
+
++ *groupId*: group ID used for batch data management.
+
+Currently, the UDMF provides the public data channel for cross-application data sharing.
+
+**Public data channel**: allows applications to write and read data. The corresponding **intention** is **DATA_HUB**.
+
+## Available APIs
+
+The following table lists the UDMF APIs. All of them are executed asynchronously in callback or promise mode. In the following table, callback-based APIs are used as an example. For more information about the APIs, see [UDMF](../reference/apis/js-apis-data-udmf.md).
+
+| API | Description |
+|-----------------------------------------------------------------------------------------|---------------------------------------------|
+| insertData(options: Options, data: UnifiedData, callback: AsyncCallback\): void | Inserts data to the UDMF public data channel. A unique data identifier is returned.|
+| updateData(options: Options, data: UnifiedData, callback: AsyncCallback\): void | Updates the data in the UDMF public data channel. |
+| queryData(options: Options, callback: AsyncCallback\>): void | Queries data in the UDMF public data channel. |
+| deleteData(options: Options, callback: AsyncCallback\>): void | Deletes data from the UDMF public data channel. The deleted data set is returned.|
+
+
+## How to Develop
+
+The following example describes how to implement many-to-many data sharing. The data provider writes data to the UMDF public data channel, and updates and deletes the data. The data consumer obtains the data shared by the data provider.
+
+### Data Provider
+
+1. Import the **@ohos.data.UDMF** module.
+
+ ```ts
+ import UDMF from '@ohos.data.UDMF';
+ ```
+2. Create a **UnifiedData** object and insert it into the UDMF public data channel.
+
+ ```ts
+ let plainText = new UDMF.PlainText();
+ plainText.textContent = 'hello world!';
+ let unifiedData = new UDMF.UnifiedData(plainText);
+
+ // Specify the type of the data channel to which the data is to be inserted.
+ let options = {
+ intention: UDMF.Intention.DATA_HUB
+ }
+ try {
+ UDMF.insertData(options, unifiedData, (err, data) => {
+ if (err === undefined) {
+ console.info(`Succeeded in inserting data. key = ${data}`);
+ } else {
+ console.error(`Failed to insert data. code is ${err.code},message is ${err.message} `);
+ }
+ });
+ } catch(e) {
+ console.error(`Insert data throws an exception. code is ${e.code},message is ${e.message} `);
+ }
+ ```
+3. Update the **UnifiedData** object inserted.
+
+ ```ts
+ let plainText = new UDMF.PlainText();
+ plainText.textContent = 'How are you!';
+ let unifiedData = new UDMF.UnifiedData(plainText);
+
+ // Specify the URI of the UnifiedData object to update.
+ let options = {
+ key: 'udmf://DataHub/com.ohos.test/0123456789'
+ };
+
+ try {
+ UDMF.updateData(options, unifiedData, (err) => {
+ if (err === undefined) {
+ console.info('Succeeded in updating data.');
+ } else {
+ console.error(`Failed to update data. code is ${err.code},message is ${err.message} `);
+ }
+ });
+ } catch(e) {
+ console.error(`Update data throws an exception. code is ${e.code},message is ${e.message} `);
+ }
+ ```
+4. Delete the **UnifiedData** object from the UDMF public data channel.
+
+ ```ts
+ // Specify the type of the data channel whose data is to be deleted.
+ let options = {
+ intention: UDMF.Intention.DATA_HUB
+ };
+
+ try {
+ UDMF.deleteData(options, (err, data) => {
+ if (err === undefined) {
+ console.info(`Succeeded in deleting data. size = ${data.length}`);
+ for (let i = 0; i < data.length; i++) {
+ let records = data[i].getRecords();
+ for (let j = 0; j < records.length; j++) {
+ if (records[j].getType() === UDMF.UnifiedDataType.PLAIN_TEXT) {
+ let text = (records[j]);
+ console.info(`${i + 1}.${text.textContent}`);
+ }
+ }
+ }
+ } else {
+ console.error(`Failed to delete data. code is ${err.code},message is ${err.message} `);
+ }
+ });
+ } catch(e) {
+ console.error(`Delete data throws an exception. code is ${e.code},message is ${e.message} `);
+ }
+ ```
+
+### Data Consumer
+
+1. Import the **@ohos.data.UDMF** module.
+
+ ```ts
+ import UDMF from '@ohos.data.UDMF';
+ ```
+2. Query the **UnifiedData** object in the UDMF public data channel.
+
+ ```ts
+ // Specify the type of the data channel whose data is to be queried.
+ let options = {
+ intention: UDMF.Intention.DATA_HUB
+ };
+
+ try {
+ UDMF.queryData(options, (err, data) => {
+ if (err === undefined) {
+ console.info(`Succeeded in querying data. size = ${data.length}`);
+ for (let i = 0; i < data.length; i++) {
+ let records = data[i].getRecords();
+ for (let j = 0; j < records.length; j++) {
+ if (records[j].getType() === UDMF.UnifiedDataType.PLAIN_TEXT) {
+ let text = (records[j]);
+ console.info(`${i + 1}.${text.textContent}`);
+ }
+ }
+ }
+ } else {
+ console.error(`Failed to query data. code is ${err.code},message is ${err.message} `);
+ }
+ });
+ } catch(e) {
+ console.error(`Query data throws an exception. code is ${e.code},message is ${e.message} `);
+ }
+ ```
diff --git a/en/application-dev/database/unified-data-definition.md b/en/application-dev/database/unified-data-definition.md
new file mode 100644
index 0000000000000000000000000000000000000000..d0a3c100b5dadff7ef56a0938cde5b4d98b489d4
--- /dev/null
+++ b/en/application-dev/database/unified-data-definition.md
@@ -0,0 +1,125 @@
+# Unified Data Definition
+
+
+## When to Use
+
+To streamline cross-application data interaction of OpenHarmony and minimize the application/service data interaction costs, the Unified Data Management Framework (UDMF) provides standard data definitions to define common data types. Applications can use the APIs provided by the UDMF to create and use these data types.
+
+
+## Unified Data Types
+
+The UDMF provides the following unified data types:
+
+**Basic data types** Basic data types include File and Text, which can be used for cross-application and cross-platform data interaction. Figure 1 and Figure 2 illustrate the basic data types.
+
+**Figure 1** UDMF File
+
+
+
+Figure 2 UDMF Text
+
+
+
+**System Defined Types (SDTs)** The SDTs are specific to the platform or operating system, such as Form (UI card information), AppItem (app description information), and PixelMap (thumbnail). This type of data can be used for cross-application data interaction in a system or platform. Figure 3 illustrates the SDT data.
+
+**Figure 3** UDMF SDT data
+
+
+
+**App Defined Type (ADT)** The SDT data is application-specific. This type of data can be used for across-platform data interaction for an application. As shown in Figure 4, the MyFile file format can be defined for use in an application ecosystem.
+
+**Figure 4** UDMF ADT data
+
+
+
+## Restrictions
+
+- The size of each data record in the UDMF cannot exceed 2 MB.
+- The UDMF supports data group management. The size of each group cannot exceed 4 MB.
+
+## Available APIs
+
+The UDMF provides the unified data object **UnifiedData** to encapsulate a group of data records **UnifiedRecord**. **UnifiedRecord** is an abstract definition of data content supported by the UDMF, for example, a text record or an image record. The data content type in a data record corresponds to **UnifiedDataType**.
+
+The following table describes common UDMF APIs. For more information, see [UDMF](../reference/apis/js-apis-data-udmf.md).
+
+| Class | API | Description |
+|---------------|-------------------|-----------------------------------------------------------------------------------------------|
+| UnifiedRecord | getType(): string | Obtains the data type of this data record.|
+| UnifiedData | constructor(record: UnifiedRecord) | A constructor used to create a **UnifiedData** object with a data record. |
+| UnifiedData | addRecord(record: UnifiedRecord): void | Adds a data record to this **UnifiedRecord** object. |
+| UnifiedData | getRecords(): Array\ | Obtains all data records from this **UnifiedData** object. The data obtained is of the **UnifiedRecord** type. You need to obtain the data type by using **getType** and convert the data type to a child class before using it.|
+
+
+## How to Develop
+
+The following describes how to create a **UnifiedData** object containing two data records: image and plain text.
+
+1. Import the **@ohos.data.UDMF** module.
+
+ ```ts
+ import UDMF from '@ohos.data.UDMF';
+ ```
+2. Create an image data record and initialize the **UnifiedData** object with the image data record.
+
+ (1) Create an image data record.
+
+ ```ts
+ let image = new UDMF.Image();
+ ```
+
+ (2) Modify object attributes.
+
+ ```ts
+ // The Image object contains the imageUri attribute.
+ image.imageUri = '...';
+ ```
+
+ (3) Access the object attributes.
+
+ ```ts
+ console.info(`imageUri = ${image.imageUri}`);
+ ```
+
+ (4) Create a **UnifiedData** instance.
+
+ ```ts
+ let unifiedData = new UDMF.UnifiedData(image);
+ ```
+3. Create a plain text data record and add it to the **UnifiedData** instance created.
+
+ ```ts
+ let plainText = new UDMF.PlainText();
+ plainText.textContent = 'this is textContent of plainText';
+ plainText.abstract = 'abstract of plainText';
+ plainText.details = {
+ plainKey1: 'plainValue1',
+ plainKey2: 'plainValue2',
+ };
+ unifiedData.addRecord(plainText);
+ ```
+4. Obtain all data records in this **UnifiedData** instance.
+
+ ```ts
+ let records = unifiedData.getRecords();
+ ```
+5. Traverse each record, determine the data type of the record, and convert the record into a child class object to obtain the original data record.
+
+ ```ts
+ for (let i = 0; i < records.length; i ++) {
+ // Read the type of the data record.
+ let type = records[i].getType();
+ switch (type) {
+ case UDMF.UnifiedDataType.IMAGE:
+ // Convert the data to obtain the original image data record.
+ let image = (records[i]);
+ break;
+ case UDMF.UnifiedDataType.PLAIN_TEXT:
+ // Convert the data to obtain the original text record.
+ let plainText = (records[i]);
+ break;
+ default:
+ break;
+ }
+ }
+ ```
diff --git a/en/application-dev/device/figures/001.png b/en/application-dev/device/figures/001.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b173958ed943fb9ecebd686b4f378d93fa2a7b0
Binary files /dev/null and b/en/application-dev/device/figures/001.png differ
diff --git a/en/application-dev/device/figures/002.png b/en/application-dev/device/figures/002.png
new file mode 100644
index 0000000000000000000000000000000000000000..34af38f77c66cbef900a1a4e536e3873bd0d94aa
Binary files /dev/null and b/en/application-dev/device/figures/002.png differ
diff --git a/en/application-dev/device/figures/003.png b/en/application-dev/device/figures/003.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c95c64ccb305ec25b1927733615ec4553505f97
Binary files /dev/null and b/en/application-dev/device/figures/003.png differ
diff --git a/en/application-dev/device/sensor-guidelines.md b/en/application-dev/device/sensor-guidelines.md
index 6ff5eb7405027da0853737ba64959cec4e59ad3a..21e1b55296ac46606bf1e4c91859f4c1f03ce030 100644
--- a/en/application-dev/device/sensor-guidelines.md
+++ b/en/application-dev/device/sensor-guidelines.md
@@ -15,65 +15,64 @@ For details about the APIs, see [Sensor](../reference/apis/js-apis-sensor.md).
| ohos.sensor | sensor.on(sensorId, callback:AsyncCallback<Response>): void | Subscribes to data changes of a type of sensor.|
| ohos.sensor | sensor.once(sensorId, callback:AsyncCallback<Response>): void | Subscribes to only one data change of a type of sensor.|
| ohos.sensor | sensor.off(sensorId, callback?:AsyncCallback<void>): void | Unsubscribes from sensor data changes.|
+| ohos.sensor | sensor.getSensorList(callback: AsyncCallback\>): void| Obtains information about all sensors on the device. This API uses an asynchronous callback to return the result.|
## How to Develop
-1. Before obtaining data from a type of sensor, check whether the required permission has been configured.
- The system provides the following sensor-related permissions:
- - ohos.permission.ACCELEROMETER
+The acceleration sensor is used as an example.
- - ohos.permission.GYROSCOPE
+1. Import the module.
- - ohos.permission.ACTIVITY_MOTION
-
- - ohos.permission.READ_HEALTH_DATA
-
- For details about how to configure a permission, see [Declaring Permissions](../security/accesstoken-guidelines.md).
-
-2. Subscribe to data changes of a type of sensor. The following uses the acceleration sensor as an example.
-
```ts
import sensor from "@ohos.sensor";
-
- sensor.on(sensor.SensorId.ACCELEROMETER, function (data) {
- console.info("Succeeded in obtaining data. x: " + data.x + "y: " + data.y + "z: " + data.z); // Data is obtained.
- });
```
-
- 
-3. Unsubscribe from sensor data changes.
-
- ```ts
- import sensor from "@ohos.sensor";
- sensor.off(sensor.SensorId.ACCELEROMETER);
- ```
-
- 
+2. Obtain information about all sensors on the device.
+
+ ```ts
+ sensor.getSensorList(function (error, data) {
+ if (error) {
+ console.info('getSensorList failed');
+ } else {
+ console.info('getSensorList success');
+ for (let i = 0; i < data.length; i++) {
+ console.info(JSON.stringify(data[i]));
+ }
+ }
+ });
+ ```
-4. Subscribe to only one data change of a type of sensor.
-
- ```ts
- import sensor from "@ohos.sensor";
+ 
- sensor.once(sensor.SensorId.ACCELEROMETER, function (data) {
- console.info("Succeeded in obtaining data. x: " + data.x + "y: " + data.y + "z: " + data.z); // Data is obtained.
- });
- ```
-
- 
+ The minimum and the maximum sampling periods supported by the sensor are 5000000 ns and 200000000 ns, respectively. Therefore, the value of **interval** must be within this range.
+
+3. Check whether the corresponding permission has been configured. For details, see [Applying for Permissions](../security/accesstoken-guidelines.md).
- If the API fails to be called, you are advised to use the **try/catch** statement to capture error information that may occur in the code. Example:
+4. Register a listener. You can call **on()** or **once()** to listen for sensor data changes.
+
+- The **on()** API is used to continuously listen for data changes of the sensor. The sensor reporting interval is set to 100000000 ns.
+
+ ```ts
+ sensor.on(sensor.SensorId.ACCELEROMETER, function (data) {
+ console.info("Succeeded in obtaining data. x: " + data.x + " y: " + data.y + " z: " + data.z);
+ }, {'interval': 100000000});
+ ```
+
+ 
+
+- The **once()** API is used to listen for only one data change of the sensor.
```ts
- import sensor from "@ohos.sensor";
+ sensor.once(sensor.SensorId.ACCELEROMETER, function (data) {
+ console.info("Succeeded in obtaining data. x: " + data.x + " y: " + data.y + " z: " + data.z);
+ });
+ ```
+
+ 
- try {
- sensor.once(sensor.SensorId.ACCELEROMETER, function (data) {
- console.info("Succeeded in obtaining data. x: " + data.x + "y: " + data.y + "z: " + data.z); // Data is obtained.
- });
- } catch (error) {
- console.error(`Failed to get sensor data. Code: ${error.code}, message: ${error.message}`);
- }
+5. Cancel continuous listening.
+
+ ```ts
+ sensor.off(sensor.SensorId.ACCELEROMETER);
```
diff --git a/en/application-dev/device/vibrator-guidelines.md b/en/application-dev/device/vibrator-guidelines.md
index 7d3434d680d0d1a369d4f0ccd0bc8f720bd71349..4619a52a2f91c94b06e529be68d78330b4a4719f 100644
--- a/en/application-dev/device/vibrator-guidelines.md
+++ b/en/application-dev/device/vibrator-guidelines.md
@@ -76,9 +76,9 @@ This JSON file contains two attributes: **MetaData** and **Channels**.
- **Create**: time when the file was created. This parameter is optional.
- **Description**: additional information such as the vibration effect and creation information. This parameter is optional.
- **Channels** provides information about the vibration channel. It is a JSON array that holds information about each channel. It contains two attributes: **Parameters** and **Pattern**.
-- **Parameters** provides parameters related to the channel. Under it, **Index** indicates the channel ID. The value is fixed at **1** for a single channel. This parameter is mandatory.
+ - **Parameters** provides parameters related to the channel. Under it, **Index** indicates the channel ID. The value is fixed at **1** for a single channel. This parameter is mandatory.
- **Pattern** indicates the vibration sequence. It is a JSON array. Under it, **Event** indicates a vibration event, which can be either of the following types:
-- **transient**: short vibration
+ - **transient**: short vibration
- **continuous**: long vibration
The table below describes the parameters under **Event**.
@@ -89,7 +89,7 @@ The table below describes the parameters under **Event**.
| StartTime | Start time of the vibration. This parameter is mandatory.| [0, 1800 000], in ms, without overlapping|
| Duration | Duration of the vibration. This parameter is valid only when **Type** is **continuous**.| (10, 1600), in ms|
| Intensity | Intensity of the vibration. This parameter is mandatory.| [0, 100], a relative value that does not represent the actual vibration strength.|
-| Frequency | Frequency of the vibration. This parameter is mandatory.| [0, 100], a relative value that does not represent the actual vibration frequency|
+| Frequency | Frequency of the vibration. This parameter is mandatory.| [0, 100], a relative value that does not represent the actual vibration frequency.|
The following requirements must be met:
@@ -221,45 +221,42 @@ The following requirements must be met:
```ts
import vibrator from '@ohos.vibrator';
- const FILE_NAME = "xxx.json";
-
// Obtain the file descriptor of the vibration configuration file.
- let fileDescriptor = undefined;
- getContext().resourceManager.getRawFd(FILE_NAME).then(value => {
- fileDescriptor = { fd: value.fd, offset: value.offset, length: value.length };
- console.info('Succeed in getting resource file descriptor');
- }).catch(error => {
- console.error(`Failed to get resource file descriptor. Code: ${error.code}, message: ${error.message}`);
- });
- // To use startVibration and stopVibration, you must configure the ohos.permission.VIBRATE permission.
- try {
- // Start custom vibration.
- vibrator.startVibration({
- type: "file",
- hapticFd: { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length }
- }, {
- usage: "alarm"
- }).then(() => {
- console.info('Succeed in starting vibration');
- }, (error) => {
- console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
- });
- // Stop vibration in all modes.
- vibrator.stopVibration(function (error) {
- if (error) {
- console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
- return;
- }
- console.info('Succeed in stopping vibration');
- })
- } catch (error) {
- console.error(`An unexpected error occurred. Code: ${error.code}, message: ${error.message}`);
+ async function getRawfileFd(fileName) {
+ let rawFd = await globalThis.getContext().resourceManager.getRawFd(fileName);
+ return rawFd;
+ }
+
+ // Close the file descriptor of the vibration configuration file.
+ async function closeRawfileFd(fileName) {
+ await globalThis.getContext().resourceManager.closeRawFd(fileName)
+ }
+
+ // Play the custom vibration. To use startVibration and stopVibration, you must configure the ohos.permission.VIBRATE permission.
+ async function playCustomHaptic(fileName) {
+ try {
+ let rawFd = await getRawfileFd(fileName);
+ vibrator.startVibration({
+ type: "file",
+ hapticFd: { fd: rawFd.fd, offset: rawFd.offset, length: rawFd.length }
+ }, {
+ usage: "alarm"
+ }).then(() => {
+ console.info('Succeed in starting vibration');
+ }, (error) => {
+ console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
+ });
+ vibrator.stopVibration(function (error) {
+ if (error) {
+ console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
+ return;
+ }
+ console.info('Succeed in stopping vibration');
+ })
+ await closeRawfileFd(fileName);
+ } catch (error) {
+ console.error(`An unexpected error occurred. Code: ${error.code}, message: ${error.message}`);
+ }
}
- // Close the vibration file.
- getContext().resourceManager.closeRawFd(FILE_NAME).then(() => {
- console.info('Succeed in closing resource file descriptor');
- }).catch(error => {
- console.error(`Failed to close resource file descriptor. Code: ${error.code}, message: ${error.message}`);
- });
```
diff --git a/en/application-dev/dfx/Readme-EN.md b/en/application-dev/dfx/Readme-EN.md
index 5a1b6326bae1ecb94ef7fe8d9e4cfe2cdf2c6c56..c40f752d8f85e8894eb725965f50a7614dddef36 100644
--- a/en/application-dev/dfx/Readme-EN.md
+++ b/en/application-dev/dfx/Readme-EN.md
@@ -1,7 +1,6 @@
# 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
diff --git a/en/application-dev/dfx/appfreeze-guidelines.md b/en/application-dev/dfx/appfreeze-guidelines.md
index 05b52c4d8070386ec350701cefb2c6b63ef67d55..4984c95e215fe832f59abc3306bf777c6c313818 100644
--- a/en/application-dev/dfx/appfreeze-guidelines.md
+++ b/en/application-dev/dfx/appfreeze-guidelines.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/dfx/apprecovery-guidelines.md b/en/application-dev/dfx/apprecovery-guidelines.md
index 284de5ca6d5f6027f2cce975a29b3259b2778021..9548404b3b359ad3f6fbe6778e0ddaeb374cc2ec 100644
--- a/en/application-dev/dfx/apprecovery-guidelines.md
+++ b/en/application-dev/dfx/apprecovery-guidelines.md
@@ -1,6 +1,6 @@
# 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("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";
diff --git a/en/application-dev/dfx/cppcrash-guidelines.md b/en/application-dev/dfx/cppcrash-guidelines.md
index 4454422fe4f3aec6c781090a2e833ee103488dab..15136518788324e23ac46c8c8b5bba327c03ea7a 100644
--- a/en/application-dev/dfx/cppcrash-guidelines.md
+++ b/en/application-dev/dfx/cppcrash-guidelines.md
@@ -1,6 +1,6 @@
-# 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.
diff --git a/en/application-dev/dfx/errormanager-guidelines.md b/en/application-dev/dfx/errormanager-guidelines.md
index 4679cfcfc78893590fe73eab770e49fc68a1a828..14d7735d731d0fb2eb3fc41f61de58f5de7f4e02 100644
--- a/en/application-dev/dfx/errormanager-guidelines.md
+++ b/en/application-dev/dfx/errormanager-guidelines.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/dfx/hiappevent-guidelines.md b/en/application-dev/dfx/hiappevent-guidelines.md
index d21d4e3fa9e0fa0b795c82e7157cd6215eab5e0c..6b0f4dd1cb8ec36288514e3f8767770f4e30105b 100644
--- a/en/application-dev/dfx/hiappevent-guidelines.md
+++ b/en/application-dev/dfx/hiappevent-guidelines.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/dfx/hilog-guidelines.md b/en/application-dev/dfx/hilog-guidelines.md
index 25b4a7f9cc5c92d9f20ed6582299d5dd65b937d0..45d46c01fb4c601241120ce9cf5d249bd0bc893f 100644
--- a/en/application-dev/dfx/hilog-guidelines.md
+++ b/en/application-dev/dfx/hilog-guidelines.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/dfx/hitracechain-guidelines.md b/en/application-dev/dfx/hitracechain-guidelines.md
index affd260b0503f3c4f4c4b748d5911d94f7fef9e3..44e2da92dfbf985f27a275ac6e02e61a934d199e 100644
--- a/en/application-dev/dfx/hitracechain-guidelines.md
+++ b/en/application-dev/dfx/hitracechain-guidelines.md
@@ -1,6 +1,6 @@
# 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.
diff --git a/en/application-dev/dfx/hitracemeter-guidelines.md b/en/application-dev/dfx/hitracemeter-guidelines.md
index a4152acb7303cd672b830d80a3ba48bc54ee8d9c..195aae4b2d98dd1ab950613c6c97ed07cfcfe98e 100644
--- a/en/application-dev/dfx/hitracemeter-guidelines.md
+++ b/en/application-dev/dfx/hitracemeter-guidelines.md
@@ -1,6 +1,6 @@
# 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.
@@ -35,51 +35,7 @@ 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';
diff --git a/en/application-dev/dfx/hitracemeter-native-guidelines.md b/en/application-dev/dfx/hitracemeter-native-guidelines.md
index bb0274f7c4077b016061430250e7a949cf826864..912ec1c5f87b6ebfdd6f14cb4da568e251501af2 100644
--- a/en/application-dev/dfx/hitracemeter-native-guidelines.md
+++ b/en/application-dev/dfx/hitracemeter-native-guidelines.md
@@ -1,6 +1,6 @@
# 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**
diff --git a/en/application-dev/faqs/Readme-EN.md b/en/application-dev/faqs/Readme-EN.md
index d7316d5a25c20f4cd076b8ebca4ed700d7c387c7..038869298ca254238293357a0c31b84c817cc9c4 100644
--- a/en/application-dev/faqs/Readme-EN.md
+++ b/en/application-dev/faqs/Readme-EN.md
@@ -2,7 +2,7 @@
- [Full SDK Compilation](full-sdk-compile-guide.md)
- [Switching to Full SDK](full-sdk-switch-guide.md)
-- [Using Native APIs (NDK) of the OpenHarmony SDK in a CMake Project](howto-migrate-cmake-with-ohosndk.md)
+- [Using NDK in a CMake Project](cmake-with-ndk.md)
- [Application Model Development](faqs-ability.md)
- ArkUI Development (ArkTS)
- [ArkTS Syntax Usage](faqs-arkui-arkts.md)
diff --git a/en/application-dev/faqs/howto-migrate-cmake-with-ohosndk.md b/en/application-dev/faqs/cmake-with-ndk.md
similarity index 92%
rename from en/application-dev/faqs/howto-migrate-cmake-with-ohosndk.md
rename to en/application-dev/faqs/cmake-with-ndk.md
index 36f339529c78327f2698f90ce199e758ba06485f..60a68a9ecf05aa95680096d67a18dd37bdda74c1 100644
--- a/en/application-dev/faqs/howto-migrate-cmake-with-ohosndk.md
+++ b/en/application-dev/faqs/cmake-with-ndk.md
@@ -1,4 +1,4 @@
-# Using Native APIs (NDK) of the OpenHarmony SDK in a CMake Project
+# Using NDK in a CMake Project
## What Is Native API
@@ -10,34 +10,34 @@ You download the Native API Development Kit (NDK) by downloading the OHOS SDK, w
- (Recommended) Acquire source code from mirrors for an officially released version. For details, see [release notes](../../release-notes/OpenHarmony-v3.2-release.md).
- Download the SDK from the SDK Manager in DevEco Studio.
-- Download the SDK from the [daily build](http://ci.openharmony.cn/dailys/dailybuilds), by clicking the download link to the **ohos-sdk-full** component.
+- Download the SDK from the [daily build](http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist), by clicking the download link to the **ohos-sdk-full** component.
-
+
## Decompressing the NDK
Place the downloaded NDK in a folder you prefer and decompress it. Below shows the directory structure after decompression.
-
+
Configure the Linux environment as follows: (Skip them if the NDK is downloaded from DevEco Studio.)
-1. Add the CMake tool that comes with the NDK to the environment variables.
+Add the CMake tool that comes with the NDK to the environment variables.
```
# Open the .bashrc file.
vim ~/.bashrc
- # Append the custom CMake path to the file. Save the file and exit.
+ # Append the custom CMake path to the file.
export PATH=~/ohos-sdk/ohos-sdk/linux/native/build-tools/cmake/bin:$PATH
# Run the source ~/.bashrc command to make the environment variables take effect.
source ~/.bashrc
```
-2. Check the default CMake path.
+Check the default CMake path.
```
# Run the which cmake command.
which cmake
- # The result should be the same as the custom path previously appended to the file.
+ # The result should be the same as the custom path previously appended to the .bashrc file.
~/ohos-sdk/ohos-sdk/linux/native/build-tools/cmake/bin/cmake
```
diff --git a/en/application-dev/faqs/faqs-ability.md b/en/application-dev/faqs/faqs-ability.md
index fef66125771888f9dfe3dce2ae4297ce858d56b8..01bd10fa524f0a7d7de7b26262562f0f5f5160ee 100644
--- a/en/application-dev/faqs/faqs-ability.md
+++ b/en/application-dev/faqs/faqs-ability.md
@@ -217,7 +217,7 @@ Use **Context.cacheDir** to obtain the cache directory of the application.
**Reference**
-[Obtaining the Application Development Path](../application-models/application-context-stage.md#obtaining-the-application-development-path)
+[cacheDir](../application-models/application-context-stage.md#obtaining-application-file-paths)
## In which JS file is the service widget lifecycle callback invoked?
@@ -262,7 +262,7 @@ Obtain them from the application context. Specifically, use **this.context.getAp
**Reference**
-[Obtaining the Application Development Path](../application-models/application-context-stage.md#obtaining-the-application-development-path)
+[Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths)
## Why the application is not deleted from the background mission list after it calls terminateSelf?
@@ -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-dev-guide.md#development-in-the-stage-model)
+[Continuous Task](../task-management/continuous-task.md)
## How do FA widgets exchange data?
diff --git a/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md b/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md
index fbe2594e6591bb774aa116095e721ca889490cc8..cc07a581e4fb9a271b566928e8a5c991185c42c8 100644
--- a/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md
+++ b/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md
@@ -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, **\**, 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 **\** 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?
@@ -191,7 +194,7 @@ struct PageTransition2 {
**Reference**
-[Page Transition Animation](../ui/arkts-page-transition-animation.md)
+[Page Transition](../reference/arkui-ts/ts-page-transition-animation.md)
## How do I configure custom components to slide in and out from the bottom?
@@ -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-transition-animation-within-component.md)
+[Enter/Exit Transition](../ui/arkts-enter-exit-transition.md)
diff --git a/en/application-dev/faqs/faqs-arkui-arkts.md b/en/application-dev/faqs/faqs-arkui-arkts.md
index 30372ac1e4f810f87e225b397b2aa5f95208ed0c..4cae24c691f9dab62d4c3452f32f69d3cf5b0da0 100644
--- a/en/application-dev/faqs/faqs-arkui-arkts.md
+++ b/en/application-dev/faqs/faqs-arkui-arkts.md
@@ -760,147 +760,6 @@ Text in the **\** component is centered by default. You do not need to set
[Text](../reference/arkui-ts/ts-basic-components-text.md#example-1)
-## How do I set the controlButton attribute for the \ component?
-
-Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
-
-**Solution**
-
-The sample code is as follows:
-
-```
-@Entry
-@Component
-struct SideBarContainerExample {
- normalIcon : Resource = $r("app.media.icon")
- selectedIcon: Resource = $r("app.media.icon")
- @State arr: number[] = [1, 2, 3]
- @State current: number = 1
-
- build() {
- SideBarContainer(SideBarContainerType.Embed)
- {
- Column() {
- ForEach(this.arr, (item, index) => {
- Column({ space: 5 }) {
- Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64)
- Text("Index0" + item)
- .fontSize(25)
- .fontColor(this.current === item ? '#0A59F7' : '#999')
- .fontFamily('source-sans-pro,cursive,sans-serif')
- }
- .onClick(() => {
- this.current = item
- })
- }, item => item)
- }.width('100%')
- .justifyContent(FlexAlign.SpaceEvenly)
- .backgroundColor('#19000000')
-
-
- Column() {
- Text('SideBarContainer content text1').fontSize(25)
- Text('SideBarContainer content text2').fontSize(25)
- }
- .margin({ top: 50, left: 20, right: 30 })
- }
- .sideBarWidth(150)
- .minSideBarWidth(50)
- .controlButton({left:32,
- top:32,
- width:32,
- height:32,
- icons:{shown: $r("app.media.icon"),
- hidden: $r("app.media.icon"),
- switching: $r("app.media.icon")}})
- .maxSideBarWidth(300)
- .onChange((value: boolean) => {
- console.info('status:' + value)
- })
- }
-}
-```
-
-## How do I implement the dragging feature for the \ component?
-
-Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
-
-**Solution**
-
-1. Set the **editMode\(true\)** attribute of the **\** component to specify whether the component enters the editing mode. In the editing mode, you can drag grid items.
-2. Set the image displayed during dragging in the [onItemDragStart](../reference/arkui-ts/ts-container-grid.md#events) callback.
-3. Obtain the drag start position and drag insertion position from the [onItemDrop](../reference/arkui-ts/ts-container-grid.md#events) callback, and complete the array position exchange logic in the [onDrag](../reference/arkui-ts/ts-universal-events-drag-drop.md#events) callback. The sample code is as follows:
-
- ```
- @Entry
- @Component
- struct GridExample {
- @State numbers: String[] = []
- scroller: Scroller = new Scroller()
- @State text: string = 'drag'
-
- @Builder pixelMapBuilder () { // Drag style
- Column() {
- Text(this.text)
- .fontSize(16)
- .backgroundColor(0xF9CF93)
- .width(80)
- .height(80)
- .textAlign(TextAlign.Center)
- }
- }
-
- aboutToAppear() {
- for (let i = 1;i <= 15; i++) {
- this.numbers.push(i + '')
- }
- }
-
- changeIndex(index1: number, index2: number) {// Exchange the array item position.
- [this.numbers[index1], this.numbers[index2]] = [this.numbers[index2], this.numbers[index1]];
- }
-
- build() {
- Column({ space: 5 }) {
- Grid(this.scroller) {
- ForEach(this.numbers, (day: string) => {
- GridItem() {
- Text(day)
- .fontSize(16)
- .backgroundColor(0xF9CF93)
- .width(80)
- .height(80)
- .textAlign(TextAlign.Center)
- .onTouch((event: TouchEvent) => {
- if (event.type === TouchType.Up) {
- this.text = day
- }
- })
- }
- })
- }
- .columnsTemplate('1fr 1fr 1fr')
- .columnsGap(10)
- .rowsGap(10)
- .onScrollIndex((first: number) => {
- console.info(first.toString())
- })
- .width('90%')
- .backgroundColor(0xFAEEE0)
- .height(300)
- .editMode(true) // Set whether the grid enters the editing mode. In the editing mode, you can drag grid items.
- .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { // Triggered when a grid item starts to be dragged.
- return this.pixelMapBuilder() // Set the image displayed during dragging.
- })
- .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { // Triggered when the dragged item is dropped on the drop target of the grid.
- console.info('beixiang' + itemIndex + '', insertIndex + '') // itemIndex indicates the initial position of the dragged item; insertIndex indicates the index of the position to which the dragged item will be dropped.
- this.changeIndex(itemIndex, insertIndex)
- })
- }.width('100%').margin({ top: 5 })
- }
- }
- ```
-
## Which API is used for URL encoding?
diff --git a/en/application-dev/faqs/faqs-arkui-component.md b/en/application-dev/faqs/faqs-arkui-component.md
index 0bb884119bda149effc09337d957ccd2231bf1c7..a61d4cb828cc8cab4b8a4636adbf66729caba10b 100644
--- a/en/application-dev/faqs/faqs-arkui-component.md
+++ b/en/application-dev/faqs/faqs-arkui-component.md
@@ -1,10 +1,10 @@
# ArkUI Component Development (ArkTS)
-## Can custom dialog boxes be defined or used in .ts files?
+## Can custom dialog boxes be defined and used in .ts files?
Applicable to: OpenHarmony 3.2 Beta 5 (API version 9)
-Unfortunately, no. ArkTS syntax is required for defining and initializing custom dialog boxes. Therefore, they can be defined and used only in .ets files.
+Unfortunately not. Custom dialog boxes require ArkTS syntax for definition and initialization. Therefore, they can be defined and used only in .ets files.
**Reference**
@@ -245,8 +245,8 @@ When a custom dialog box contains a child component whose area size can be chang
**Solution**
-- Method 1: Use the default style of the custom dialog box. In this case, the dialog box automatically adapts its width to the grid system and its height to the child components; the maximum height is 90% of the container height.
-- Method 2: Use a custom style of the custom dialog box. In this case, the dialog box automatically adapts its width and height to the child components.
+- Method 1: Set the custom dialog box to the default style. In this style, the dialog box automatically adapts its width to the grid system and its height to the child components; the maximum height is 90% of the container height.
+- Method 2: Set the custom dialog box to a custom style. In this style, the dialog box automatically adapts its width and height to the child components.
**Reference**
@@ -685,3 +685,64 @@ You can use **focusControl.requestFocus** to control the focus of the text input
**Reference**
[Focus Control](../reference/arkui-ts/ts-universal-attributes-focus.md)
+
+## How do I set the controlButton attribute for the \ component?
+
+Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
+
+**Solution**
+
+Refer to the following sample code:
+
+```
+@Entry
+@Component
+struct SideBarContainerExample {
+ normalIcon : Resource = $r("app.media.icon")
+ selectedIcon: Resource = $r("app.media.icon")
+ @State arr: number[] = [1, 2, 3]
+ @State current: number = 1
+
+ build() {
+ SideBarContainer(SideBarContainerType.Embed)
+ {
+ Column() {
+ ForEach(this.arr, (item, index) => {
+ Column({ space: 5 }) {
+ Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64)
+ Text("Index0" + item)
+ .fontSize(25)
+ .fontColor(this.current === item ? '#0A59F7' : '#999')
+ .fontFamily('source-sans-pro,cursive,sans-serif')
+ }
+ .onClick(() => {
+ this.current = item
+ })
+ }, item => item)
+ }.width('100%')
+ .justifyContent(FlexAlign.SpaceEvenly)
+ .backgroundColor('#19000000')
+
+
+ Column() {
+ Text('SideBarContainer content text1').fontSize(25)
+ Text('SideBarContainer content text2').fontSize(25)
+ }
+ .margin({ top: 50, left: 20, right: 30 })
+ }
+ .sideBarWidth(150)
+ .minSideBarWidth(50)
+ .controlButton({left:32,
+ top:32,
+ width:32,
+ height:32,
+ icons:{shown: $r("app.media.icon"),
+ hidden: $r("app.media.icon"),
+ switching: $r("app.media.icon")}})
+ .maxSideBarWidth(300)
+ .onChange((value: boolean) => {
+ console.info('status:' + value)
+ })
+ }
+}
+```
diff --git a/en/application-dev/faqs/faqs-graphics.md b/en/application-dev/faqs/faqs-graphics.md
index 345cbf83c5b2976c810e78237cb2587eaa4b1404..4cc8b196d5b8210e2360a598c1b24fdc0edb891b 100644
--- a/en/application-dev/faqs/faqs-graphics.md
+++ b/en/application-dev/faqs/faqs-graphics.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)
diff --git a/en/application-dev/faqs/faqs-multimedia.md b/en/application-dev/faqs/faqs-multimedia.md
index 6d15bc704000f19b61d2f753b46a38592b052f06..e6f9e571cfe88717192e1a1725cd6adf29bd3745 100644
--- a/en/application-dev/faqs/faqs-multimedia.md
+++ b/en/application-dev/faqs/faqs-multimedia.md
@@ -98,7 +98,7 @@ Music cannot be played in the background.
**Reference**
-[Continuous Task Development](../task-management/continuous-task-dev-guide.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)
diff --git a/en/application-dev/file-management/Readme-EN.md b/en/application-dev/file-management/Readme-EN.md
index f976a47e09917c74f143a5cd84f3e7824825dc47..ba9de10386b364074c8e1c1f87fc40af39c5e053 100644
--- a/en/application-dev/file-management/Readme-EN.md
+++ b/en/application-dev/file-management/Readme-EN.md
@@ -1,31 +1,31 @@
# 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)
diff --git a/en/application-dev/file-management/app-file-access.md b/en/application-dev/file-management/app-file-access.md
index a98e1ec1d8e82af603621f8cb41bad58ecc79d93..4d3a21c0902535a3d81fd4be678973b6e8dfab23 100644
--- a/en/application-dev/file-management/app-file-access.md
+++ b/en/application-dev/file-management/app-file-access.md
@@ -1,42 +1,42 @@
# 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. 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. 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);
diff --git a/en/application-dev/file-management/app-file-backup-extension.md b/en/application-dev/file-management/app-file-backup-extension.md
index 3ba491045e1dc665bbc13d9edb9431e79e7809a6..005c772600ba3e078b30221d6d0bb711173cbd6a 100644
--- a/en/application-dev/file-management/app-file-backup-extension.md
+++ b/en/application-dev/file-management/app-file-backup-extension.md
@@ -1,19 +1,19 @@
-# 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. Each item in the array is a pattern string, which can contain shell-style wildcards such as *****, **?**, and **[**. The pattern string that does not start with a slash (/) indicates a relative path relative to the root path. 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**. 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. Each item in the array is a pattern string, which can contain shell-style wildcards such as (`*`, `?`, `[`). The pattern string that does not start with a slash (/) indicates a relative path. 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**. 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:
@@ -73,8 +73,8 @@ BackupExtensionAbility is a class derived from the [ExtensionAbility](../applica
"data/storage/el2/base/files/",
"data/storage/el2/base/preferences/",
"data/storage/el2/base/haps/*/database/",
- "data/storage/el2/base/haps/*/base/files/",
- "data/storage/el2/base/haps/*/base/preferences/",
+ "data/storage/el2/base/haps/*/files/",
+ "data/storage/el2/base/haps/*/preferences/",
]
}
-```
+```
\ No newline at end of file
diff --git a/en/application-dev/file-management/app-file-backup-overview.md b/en/application-dev/file-management/app-file-backup-overview.md
index c18cf73bfd407bd7f626edda73cc3b815de6155a..ecfceb9df408b35c5adec20db0b91e186da155b1 100644
--- a/en/application-dev/file-management/app-file-backup-overview.md
+++ b/en/application-dev/file-management/app-file-backup-overview.md
@@ -1,15 +1,15 @@
# 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.
diff --git a/en/application-dev/file-management/app-file-backup.md b/en/application-dev/file-management/app-file-backup.md
index 991e228e680ad4a0b7e1e23636df52f3996b8452..ccfb8641f4db47a71029c2c4591382081aeb0697 100644
--- a/en/application-dev/file-management/app-file-backup.md
+++ b/en/application-dev/file-management/app-file-backup.md
@@ -1,14 +1,14 @@
-# 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');
},
diff --git a/en/application-dev/file-management/app-file-overview.md b/en/application-dev/file-management/app-file-overview.md
index f3d49fd0c640ca1602575a917c37fc7f97818842..d1176912225ad505bc245889d1e38291156c29e5 100644
--- a/en/application-dev/file-management/app-file-overview.md
+++ b/en/application-dev/file-management/app-file-overview.md
@@ -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
diff --git a/en/application-dev/file-management/app-file-upload-download.md b/en/application-dev/file-management/app-file-upload-download.md
index a73fc9568cc03e791074866c20dc963b028cdb55..75fb0646cf2dbfa1422209c4d4b9b176e547f749 100644
--- a/en/application-dev/file-management/app-file-upload-download.md
+++ b/en/application-dev/file-management/app-file-upload-download.md
@@ -1,6 +1,6 @@
# 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.
>
-> 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.
>
-> 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.
diff --git a/en/application-dev/file-management/app-fs-space-statistics.md b/en/application-dev/file-management/app-fs-space-statistics.md
index 9596834a5b5bda14e810061817dcdf55da3aaf3a..74ffbc6c6f39441be0a9c0043389458025bc0c0d 100644
--- a/en/application-dev/file-management/app-fs-space-statistics.md
+++ b/en/application-dev/file-management/app-fs-space-statistics.md
@@ -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: **/data/storage/el1/bundle **|
-| cacheSize | Size of the application cache files, in bytes.| Application cache file directories: **/data/storage/el1/base/cache** **/data/storage/el1/base/haps/entry/cache** **/data/storage/el2/base/cache** **/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. - Local application file directories (parent directories of the **cache** directories): **/data/storage/el1/base** **/data/storage/el2/base** - Distributed application directory: /data/storage/el2/distributedfiles - Database directories: **/data/storage/el1/database** **/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 /data/storage/el1/base/haps/entry/cache /data/storage/el2/base/cache /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. - Local application file directories (parent directories of the **cache** directories): **/data/storage/el1/base** **/data/storage/el2/base** - Distributed application directory: **/data/storage/el2/distributedfiles** - Database directories: **/data/storage/el1/database** **/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";
diff --git a/en/application-dev/file-management/app-sandbox-directory.md b/en/application-dev/file-management/app-sandbox-directory.md
index 1f012ece997fa09706d01353cbf91dfc80bb945f..66cfb57126c94f406a5696a492afbad58168a923 100644
--- a/en/application-dev/file-management/app-sandbox-directory.md
+++ b/en/application-dev/file-management/app-sandbox-directory.md
@@ -1,29 +1,31 @@
# 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 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 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

-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.
- 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. This directory is cleared when the application is uninstalled. 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. This directory is cleared when the application is uninstalled. 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/**. 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. 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. 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. 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. 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
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
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
+ - Cache application file directory
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
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
- 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
diff --git a/en/application-dev/file-management/dev-user-file-manager.md b/en/application-dev/file-management/dev-user-file-manager.md
index 26181bb321310d1261ce2b87138b7fd2aa118552..ffcea027cfc56ad761064bd686f06452bc6be390 100644
--- a/en/application-dev/file-management/dev-user-file-manager.md
+++ b/en/application-dev/file-management/dev-user-file-manager.md
@@ -1,23 +1,23 @@
-# 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.
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.
+ 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");
diff --git a/en/application-dev/file-management/distributed-fs-overview.md b/en/application-dev/file-management/distributed-fs-overview.md
index aaa8235b947033ab95905aa1e393bc6fd78d622f..43bd19ff7ff4f1e90a5ea975c0247a666edf43b5 100644
--- a/en/application-dev/file-management/distributed-fs-overview.md
+++ b/en/application-dev/file-management/distributed-fs-overview.md
@@ -1,12 +1,12 @@
# 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.
diff --git a/en/application-dev/file-management/file-access-across-devices.md b/en/application-dev/file-management/file-access-across-devices.md
index 840078f5f982d55a9d9a3713fafa49d632d352f8..1fefd8c41154597235e718b77309f34c94a36778 100644
--- a/en/application-dev/file-management/file-access-across-devices.md
+++ b/en/application-dev/file-management/file-access-across-devices.md
@@ -1,16 +1,20 @@
-# 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';
diff --git a/en/application-dev/file-management/file-management-overview.md b/en/application-dev/file-management/file-management-overview.md
index 2fbd4b4a036de1f20f8aa64825ab1dcb60f23414..50248aaf0dc767cb8be20b20114a2bf398167378 100644
--- a/en/application-dev/file-management/file-management-overview.md
+++ b/en/application-dev/file-management/file-management-overview.md
@@ -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
diff --git a/en/application-dev/file-management/manage-external-storage.md b/en/application-dev/file-management/manage-external-storage.md
index bd5c01712cb48d6b8ac151b67a5b747967882870..b26a17455725e769f41cf1eb2cdc6d214ee3a0e9 100644
--- a/en/application-dev/file-management/manage-external-storage.md
+++ b/en/application-dev/file-management/manage-external-storage.md
@@ -1,8 +1,8 @@
# 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.
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.
+ 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) {
diff --git a/en/application-dev/file-management/photoAccessHelper-notify-guidelines.md b/en/application-dev/file-management/photoAccessHelper-notify-guidelines.md
index 6e85789e72b92b991a654482a232100017cc0cbd..b5a7f381053593a806b40d2214a5bb4777a1b83d 100644
--- a/en/application-dev/file-management/photoAccessHelper-notify-guidelines.md
+++ b/en/application-dev/file-management/photoAccessHelper-notify-guidelines.md
@@ -1,11 +1,11 @@
-# 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).
+> 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. If **uri** is the URI of a **fileAsset**, 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 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';
diff --git a/en/application-dev/file-management/photoAccessHelper-overview.md b/en/application-dev/file-management/photoAccessHelper-overview.md
index 48bb753cf4c1b5d10132c4bb1b12e7cf9290fd4c..8c66669b4e5992b1a23dd60e9c5f3ae4fe5fc5f0 100644
--- a/en/application-dev/file-management/photoAccessHelper-overview.md
+++ b/en/application-dev/file-management/photoAccessHelper-overview.md
@@ -1,14 +1,14 @@
# 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** 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. 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. 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';
diff --git a/en/application-dev/file-management/photoAccessHelper-resource-guidelines.md b/en/application-dev/file-management/photoAccessHelper-resource-guidelines.md
index d145589c1ad96aa8c9e4cc11d3112e40f4772678..a0557bcb2c264b2e1a641e489d2f62bf50deaf54 100644
--- a/en/application-dev/file-management/photoAccessHelper-resource-guidelines.md
+++ b/en/application-dev/file-management/photoAccessHelper-resource-guidelines.md
@@ -1,17 +1,17 @@
-# 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).
+> 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 the image asset.
+2. Call **PhotoAccessHelper.getAssets** to obtain image assets.
```ts
try {
@@ -70,7 +70,7 @@ let fetchOptions = {
};
```
-Call **PhotoAccessHelper.getAssets** to obtain the image asset.
+Call **PhotoAccessHelper.getAssets** to obtain image assets.
```ts
try {
@@ -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,14 +96,14 @@ 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
};
```
-Call **PhotoAccessHelper.getAssets** to obtain the image assets.
+Call **PhotoAccessHelper.getAssets** to obtain image assets.
```ts
try {
@@ -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.
diff --git a/en/application-dev/file-management/photoAccessHelper-systemAlbum-guidelines.md b/en/application-dev/file-management/photoAccessHelper-systemAlbum-guidelines.md
index 7c98b2f674aba77a5359179e2a56b56819784eb1..e42d7bab28aa84d141bcc4fe385618bfd16114ca 100644
--- a/en/application-dev/file-management/photoAccessHelper-systemAlbum-guidelines.md
+++ b/en/application-dev/file-management/photoAccessHelper-systemAlbum-guidelines.md
@@ -1,18 +1,18 @@
-# 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).
+> 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).
-2. Set **isFavorite** to **false**.
-3. Use **FileAsset.favorite** to remove the image from **Favorites**.
+1. [Obtain the images and videos in **Favorites**](#obtaining-images-and-videos-in-favorites).
+2. Set **favoriteState** to **false**.
+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**
diff --git a/en/application-dev/file-management/photoAccessHelper-userAlbum-guidelines.md b/en/application-dev/file-management/photoAccessHelper-userAlbum-guidelines.md
index 57bed20da0011c46f9172a87c121adc5f5c37f41..87d0fa3517e1ca3fcc6e4e494b5e0bcff229b80a 100644
--- a/en/application-dev/file-management/photoAccessHelper-userAlbum-guidelines.md
+++ b/en/application-dev/file-management/photoAccessHelper-userAlbum-guidelines.md
@@ -1,13 +1,13 @@
-# 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).
+> 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**.
diff --git a/en/application-dev/file-management/save-user-file.md b/en/application-dev/file-management/save-user-file.md
index db6ad37908be0a1fe1dd00e36c4553830bf03c72..a5cc3306c680ec9f5d1463de940e1844c5692a19 100644
--- a/en/application-dev/file-management/save-user-file.md
+++ b/en/application-dev/file-management/save-user-file.md
@@ -2,58 +2,105 @@
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**.
+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 files in the file manager, not in **Gallery**.
## Saving Images or Video Files
-1. Import the **picker** module and **fs** module.
+For example, select an image from **Gallery** and save it to the file manager.
+
+1. Import the [picker](../reference/apis/js-apis-file-picker.md), [fs](../reference/apis/js-apis-file-fs.md), [photoAccessHelper](../reference/apis/js-apis-photoAccessHelper.md), and [dataSharePredicates](../reference/apis/js-apis-data-dataSharePredicates.md) modules.
```ts
import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
+ import photoAccessHelper from '@ohos.file.photoAccessHelper';
+ import dataSharePredicates from '@ohos.data.dataSharePredicates';
```
-2. Create a **photoSaveOptions** instance.
+2. Obtain the thumbnail of the first image on the device. Before performing this operation, ensure that at least one image exists on the device.
```ts
- const photoSaveOptions = new picker.PhotoSaveOptions(); // Create a photoSaveOptions instance.
- photoSaveOptions.newFileNames = ["PhotoViewPicker01.jpg"]; // (Optional) Set the names of the files to save.
+ const context = getContext(this);
+ let photoAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
+
+ let pixelmapArrayBuffer;
+ async getPixelmap() {
+ try {
+ let predicates = new dataSharePredicates.DataSharePredicates();
+ let fetchOption = {
+ fetchColumns: [],
+ predicates: predicates
+ };
+ let fetchResult = await photoAccessHelper.getAssets(fetchOption);
+ console.info('[picker] getThumbnail fetchResult: ' + fetchResult);
+ const asset = await fetchResult.getFirstObject();
+ console.info('[picker] getThumbnail asset displayName = ', asset.displayName);
+ asset.getThumbnail().then((pixelMap) => {
+ let pixelBytesNumber = pixelMap.getPixelBytesNumber();
+ const readBuffer = new ArrayBuffer(pixelBytesNumber);
+ pixelMap.readPixelsToBuffer(readBuffer).then(() => {
+ pixelmapArrayBuffer = readBuffer;
+ })
+ }).catch((err) => {
+ console.error('[picker] getThumbnail failed with error: ' + err);
+ });
+ } catch (error) {
+ console.error('[picker] getThumbnail error = ' + error);
+ }
+ }
```
-3. Create a **photoViewPicker** instance and call [save()](../reference/apis/js-apis-file-picker.md#save) 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 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 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.
-
- ```ts
- let URI = null;
- const photoViewPicker = new picker.PhotoViewPicker();
- photoViewPicker.save(photoSaveOptions).then((photoSaveResult) => {
- URI = photoSaveResult[0];
- console.info('photoViewPicker.save to file succeed and URI is:' + URI);
- }).catch((err) => {
- console.error(`Invoke photoViewPicker.save failed, code is ${err.code}, message is ${err.message}`);
- })
+ 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;
+ async photoViewPickerSave() {
+ try {
+ const photoSaveOptions = new picker.PhotoSaveOptions(); // Create a photoSaveOptions instance.
+ photoSaveOptions.newFileNames = ["PhotoViewPicker01.png"]; // (Optional) Name of the file to be saved. The file name in the square brackets can be customized and must be unique. If the file name already exists on the device, change the file name. Otherwise, an error will be returned.
+
+ const photoViewPicker = new picker.PhotoViewPicker();
+ try {
+ let photoSaveResult = await photoViewPicker.save(photoSaveOptions);
+ if (photoSaveResult != undefined) {
+ console.info("[picker] photoViewPickerSave photoSaveResult = " + JSON.stringify(photoSaveResult));
+ this.uri = photoSaveResult[0];
+ console.info('photoViewPicker.save to file succeed and uri is:' + photoSaveResult[0]);
+ }
+ } catch (err) {
+ console.error(`[picker] Invoke photoViewPicker.save failed, code is ${err.code}, message is ${err.message}`);
+ }
+ } catch (error) {
+ console.info("[picker] photoViewPickerSave error = " + error);
+ }
+ }
```
-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**.
-
- ```ts
- let file = fs.openSync(URI, fs.OpenMode.READ_WRITE);
- console.info('file fd: ' + file.fd);
- ```
+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**.
-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.
+ 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
- let writeLen = fs.writeSync(file.fd, 'hello, world');
- console.info('write data to file succeed and size is:' + writeLen);
- fs.closeSync(file);
+ async writeOnly(uri) {
+ try {
+ let file = fs.openSync(uri, fs.OpenMode.WRITE_ONLY);
+ let writeLen = await fs.write(file.fd, pixelmapArrayBuffer);
+ fs.closeSync(file);
+ console.info("[picker] writeOnly writeLen = " + writeLen);
+ } catch (error) {
+ console.info("[picker] writeOnly error: " + error);
+ }
+ }
```
## Saving Documents
-1. Import the **picker** module and **fs** module.
+1. Import the **picker** and **fs** modules.
```ts
import picker from '@ohos.file.picker';
@@ -64,32 +111,32 @@ The operations for saving images, audio or video clips, and documents are simila
```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;
+ let uri = null;
const documentViewPicker = new picker.DocumentViewPicker(); // Create a documentViewPicker instance.
documentViewPicker.save(documentSaveOptions).then((documentSaveResult) => {
- URI = documentSaveResult[0];
- console.info('documentViewPicker.save to file succeed and URI is:' + URI);
+ uri = documentSaveResult[0];
+ console.info('documentViewPicker.save to file succeed and uri is:' + uri);
}).catch((err) => {
console.error(`Invoke documentViewPicker.save failed, code is ${err.code}, message is ${err.message}`);
})
```
-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);
+ 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');
@@ -99,7 +146,7 @@ The operations for saving images, audio or video clips, and documents are simila
## 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';
@@ -110,32 +157,32 @@ The operations for saving images, audio or video clips, and documents are simila
```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;
+ let uri = null;
const audioViewPicker = new picker.AudioViewPicker();
audioViewPicker.save(audioSaveOptions).then((audioSelectResult) => {
- URI = audioSelectResult[0];
- console.info('audioViewPicker.save to file succeed and URI is:' + URI);
+ uri = audioSelectResult[0];
+ console.info('audioViewPicker.save to file succeed and uri is:' + uri);
}).catch((err) => {
console.error(`Invoke audioViewPicker.save failed, code is ${err.code}, message is ${err.message}`);
})
```
-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);
+ 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 file based on the FD, and then close the FD.
```ts
let writeLen = fs.writeSync(file.fd, 'hello, world');
diff --git a/en/application-dev/file-management/select-user-file.md b/en/application-dev/file-management/select-user-file.md
index 853aae60d7e73fa4238e388eefb19ded0ca59b1d..041d20f308e47b7757de53a4735958e54bba6f2e 100644
--- a/en/application-dev/file-management/select-user-file.md
+++ b/en/application-dev/file-management/select-user-file.md
@@ -1,18 +1,18 @@
# 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.
+ 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.
@@ -35,27 +35,27 @@ The **FilePicker** provides the following interfaces by file type:
4. Create a **photoPicker** instance and call [select()](../reference/apis/js-apis-file-picker.md#select) to open the **FilePicker** page for the user to select files. After the files are selected, [PhotoSelectResult](../reference/apis/js-apis-file-picker.md#photoselectresult) is returned.
- The permission on the URIs returned by **select()** is read-only. Further file operations can be performed based on the URIs in the **PhotoSelectResult**. 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 URIs returned by **select()** is read-only. Further file operations can be performed based on the URIs in the **PhotoSelectResult**. 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;
+ let uri = null;
const photoViewPicker = new picker.PhotoViewPicker();
photoViewPicker.select(photoSelectOptions).then((photoSelectResult) => {
- URI = photoSelectResult.photoUris[0];
- console.info('photoViewPicker.select to file succeed and URI is:' + URI);
+ uri = photoSelectResult.photoUris[0];
+ console.info('photoViewPicker.select to file succeed and uri is:' + uri);
}).catch((err) => {
console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
-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);
+ 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';
@@ -81,20 +81,20 @@ The **FilePicker** provides the following interfaces by file type:
3. Create a **documentViewPicker** instance, and call [**select()**](../reference/apis/js-apis-file-picker.md#select-3) to open the **FilePicker** page for the user to select documents. After the documents are selected, a result set containing the file URIs is returned.
- 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.
+ 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**
>
> Currently, **DocumentSelectOptions** is not configurable. By default, all types of user files are selected.
```ts
- let URI = null;
+ let uri = null;
const documentViewPicker = new picker.DocumentViewPicker(); // Create a documentViewPicker instance.
documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => {
- URI = documentSelectResult[0];
- console.info('documentViewPicker.select to file succeed and URI is:' + URI);
+ uri = documentSelectResult[0];
+ console.info('documentViewPicker.select to file succeed and uri is:' + uri);
}).catch((err) => {
console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
@@ -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);
+ 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';
@@ -160,33 +160,33 @@ The **FilePicker** provides the following interfaces by file type:
3. Create an **audioViewPicker** instance, and call [**select()**](../reference/apis/js-apis-file-picker.md#select-6) to open the **FilePicker** page for the user to select audio files. After the files are selected, a result set containing the URIs of the audio files selected is returned.
- 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.
+ 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, use the [file management interface](../reference/apis/js-apis-file-fs.md) to obtain the file handle (FD) of the audio clip based on the URI, and then develop the audio playback function based on the media service. For details, see [Audio Playback Development](../media/audio-playback-overview.md).
+ For example, use the [file management interface](../reference/apis/js-apis-file-fs.md) to obtain the file handle (FD) of the audio clip based on the URI, and then develop the audio playback function based on the media service. For details, see [Audio Playback Development](../media/audio-playback-overview.md).
> **NOTE**
>
> Currently, **AudioSelectOptions** is not configurable. By default, all types of user files are selected.
```ts
- let URI = null;
+ let uri = null;
const audioViewPicker = new picker.AudioViewPicker();
audioViewPicker.select(audioSelectOptions).then(audioSelectResult => {
- URI = audioSelectOptions[0];
- console.info('audioViewPicker.select to file succeed and URI is:' + URI);
+ uri = audioSelectOptions[0];
+ console.info('audioViewPicker.select to file succeed and uri is:' + uri);
}).catch((err) => {
console.error(`Invoke audioViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
-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);
+ 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);
diff --git a/en/application-dev/file-management/send-file-to-app-sandbox.md b/en/application-dev/file-management/send-file-to-app-sandbox.md
index fdcee889e0ce2a8c51fb9db66a0c1d3e414a0d1b..af3dde8be74d5f2ddc40d2f78672d5801a09ec89 100644
--- a/en/application-dev/file-management/send-file-to-app-sandbox.md
+++ b/en/application-dev/file-management/send-file-to-app-sandbox.md
@@ -1,10 +1,10 @@
-# 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/**, 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.
diff --git a/en/application-dev/file-management/set-security-label.md b/en/application-dev/file-management/set-security-label.md
index af819fba397d47f81b0ebe005e67f9e6c8ebef39..2bf82ab58daa28d82b3c9a7ec2c38162a6ad210c 100644
--- a/en/application-dev/file-management/set-security-label.md
+++ b/en/application-dev/file-management/set-security-label.md
@@ -1,6 +1,6 @@
# 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';
diff --git a/en/application-dev/file-management/share-app-file.md b/en/application-dev/file-management/share-app-file.md
index c2f8f8d12f5ff056e043fb632cff9752c95256ce..76dbcab2a74b6b6a4afdcee72c4535939cf3e0a0 100644
--- a/en/application-dev/file-management/share-app-file.md
+++ b/en/application-dev/file-management/share-app-file.md
@@ -1,10 +1,10 @@
# 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://<bundleName>/<path>
+ **file**://<*bundleName*>/<*path*>
- **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
diff --git a/en/application-dev/file-management/user-file-overview.md b/en/application-dev/file-management/user-file-overview.md
index 599da1024166be5c00619aa71f19f6f10fd73f7f..034eabb1bce098e548a4a2fd95c8b1b62d5ceb42 100644
--- a/en/application-dev/file-management/user-file-overview.md
+++ b/en/application-dev/file-management/user-file-overview.md
@@ -1,60 +1,61 @@
# 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
+ 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
+ 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)
+ 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
+

-- 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.
diff --git a/en/application-dev/media/Readme-EN.md b/en/application-dev/media/Readme-EN.md
index e118468c6f24d6815d36c3b72a9d0ddc641ba468..b1ab8672c0a6ed63c781027c41541657b39e31ee 100755
--- a/en/application-dev/media/Readme-EN.md
+++ b/en/application-dev/media/Readme-EN.md
@@ -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)
diff --git a/en/application-dev/media/audio-decoding.md b/en/application-dev/media/audio-decoding.md
index 77631eefec952c5142d76680abd49bd694541ab1..2fc2d11ed4bf946f90466e45b6160e8880e4d7e1 100644
--- a/en/application-dev/media/audio-decoding.md
+++ b/en/application-dev/media/audio-decoding.md
@@ -73,33 +73,33 @@ The figure below shows the call relationship of audio decoding.
```
2. Call **OH_AudioDecoder_SetCallback()** to set callback functions.
-
+
Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
-
- - **OnError**, a callback used to report a codec operation error
- - **OnOutputFormatChanged**, a callback used to report a codec stream change, for example, audio channel change
- - **OnInputBufferAvailable**, a callback used to report input data required, which means that the decoder is ready for receiving data
- - **OnOutputBufferAvailable**, a callback used to report output data generated, which means that decoding is complete
+
+ - **OH_AVCodecOnError**, a callback used to report a codec operation error
+ - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
+ - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the decoder is ready for receiving data
+ - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that decoding is complete
You need to process the callback functions to ensure that the decoder runs properly.
-
- ```cpp
- // Set the OnError callback function.
+
+ ```cpp
+ // Implement the OH_AVCodecOnError callback function.
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
(void)codec;
(void)errorCode;
(void)userData;
}
- // Set the OnOutputFormatChanged callback function.
- static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, 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;
}
- // Set the OnInputBufferAvailable callback function, which is used to send the input stream to the InputBuffer queue.
- static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory*data, void *userData)
+ // Implement the OH_AVCodecOnNeedInputData callback function.
+ static void onNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory*data, void *userData)
{
(void)codec;
ADecSignal *signal = static_cast(userData);
@@ -109,8 +109,8 @@ The figure below shows the call relationship of audio decoding.
signal->inCond_.notify_all();
// The input stream is sent to the InputBuffer queue.
}
- // Set the OnOutputBufferAvailable callback function, which is used to send the PCM stream obtained after decoding to the OutputBuffer queue.
- static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory*data, OH_AVCodecBufferAttr *attr,
+ // 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;
@@ -126,14 +126,13 @@ The figure below shows the call relationship of audio decoding.
// The decoded data is sent to the OutputBuffer queue.
}
signal_ = new ADecSignal();
- OH_AVCodecAsyncCallback cb = {&OnError, &OnOutputFormatChanged, OnInputBufferAvailable, &OnOutputBufferAvailable};
+ OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &onNeedInputData, &onNeedOutputData};
// Set the asynchronous callbacks.
int32_t ret = OH_AudioDecoder_SetCallback(audioDec, cb, signal_);
if (ret != AV_ERR_OK) {
// Exception handling.
}
- ```
-
+ ```
3. Call **OH_AudioDecoder_Configure()** to configure the decoder.
The following options are mandatory: sampling rate, bit rate, and number of audio channels. The maximum input length is optional.
@@ -141,7 +140,7 @@ The figure below shows the call relationship of audio decoding.
- For AAC decoding, the parameter that specifies whether the data type is Audio Data Transport Stream (ADTS) must be specified. If this parameter is not specified, the data type is considered as Low Overhead Audio Transport Multiplex (LATM).
- For Vorbis decoding, the ID header and setup header must also be specified.
- ```cpp
+ ```cpp
enum AudioFormatType : int32_t {
TYPE_AAC = 0,
TYPE_FLAC = 1,
@@ -176,8 +175,7 @@ The figure below shows the call relationship of audio decoding.
if (ret != AV_ERR_OK) {
// Exception handling.
}
- ```
-
+ ```
4. Call **OH_AudioDecoder_Prepare()** to prepare internal resources for the decoder.
```cpp
@@ -186,7 +184,6 @@ The figure below shows the call relationship of audio decoding.
// Exception handling.
}
```
-
5. Call **OH_AudioDecoder_Start()** to start the decoder.
```c++
@@ -202,12 +199,10 @@ The figure below shows the call relationship of audio decoding.
// Exception handling.
}
```
-
6. Call **OH_AudioDecoder_PushInputData()** to write the data to decode.
To indicate the End of Stream (EOS), pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag.
-
- ```c++
+ ```c++
// Configure the buffer information.
OH_AVCodecBufferAttr info;
// Set the package size, offset, and timestamp.
@@ -228,8 +223,7 @@ The figure below shows the call relationship of audio decoding.
if (ret != AV_ERR_OK) {
// Exception handling.
}
- ```
-
+ ```
7. Call **OH_AudioDecoder_FreeOutputData()** to output decoded PCM streams.
```c++
@@ -244,7 +238,6 @@ The figure below shows the call relationship of audio decoding.
// Exception handling.
}
```
-
8. (Optional) Call **OH_AudioDecoder_Flush()** to refresh the decoder.
After **OH_AudioDecoder_Flush()** is called, the decoder remains in the running state, but the current queue is cleared and the buffer storing the decoded data is freed. To continue decoding, you must call **OH_AudioDecoder_Start()** again.
@@ -265,24 +258,22 @@ The figure below shows the call relationship of audio decoding.
// Exception handling.
}
```
-
9. (Optional) Call **OH_AudioDecoder_Reset()** to reset the decoder.
After **OH_AudioDecoder_Reset()** is called, the decoder returns to the initialized state. To continue decoding, you must call **OH_AudioDecoder_Configure()** and then **OH_AudioDecoder_Start()**.
-
- ```c++
- // Reset the decoder.
- ret = OH_AudioDecoder_Reset(audioDec);
- if (ret != AV_ERR_OK) {
- // Exception handling.
- }
- // Reconfigure the decoder.
- ret = OH_AudioDecoder_Configure(audioDec, format);
- if (ret != AV_ERR_OK) {
- // Exception handling.
- }
- ```
-
+
+ ```c++
+ // Reset the decoder.
+ ret = OH_AudioDecoder_Reset(audioDec);
+ if (ret != AV_ERR_OK) {
+ // Exception handling.
+ }
+ // Reconfigure the decoder.
+ ret = OH_AudioDecoder_Configure(audioDec, format);
+ if (ret != AV_ERR_OK) {
+ // Exception handling.
+ }
+ ```
10. Call **OH_AudioDecoder_Stop()** to stop the decoder.
```c++
@@ -293,18 +284,17 @@ The figure below shows the call relationship of audio decoding.
}
return ret;
```
-
11. Call **OH_AudioDecoder_Destroy()** to destroy the decoder instance and release resources.
- **NOTE**: You only need to call this API once.
-
- ```c++
- // Call OH_AudioDecoder_Destroy to destroy the decoder.
- ret = OH_AudioDecoder_Destroy(audioDec);
- if (ret != AV_ERR_OK) {
- // Exception handling.
- } else {
- audioEnc = NULL; // The decoder cannot be destroyed repeatedly.
- }
- return ret;
- ```
\ No newline at end of file
+ **NOTE**: You only need to call this API once.
+
+ ```c++
+ // Call OH_AudioDecoder_Destroy to destroy the decoder.
+ ret = OH_AudioDecoder_Destroy(audioDec);
+ if (ret != AV_ERR_OK) {
+ // Exception handling.
+ } else {
+ audioEnc = NULL; // The decoder cannot be destroyed repeatedly.
+ }
+ return ret;
+ ```
diff --git a/en/application-dev/media/audio-effect-management.md b/en/application-dev/media/audio-effect-management.md
index e1de3111d8b776c87e5bf772b33ea619df813ced..884a9a9636e23f46b44ae73e5e75756bea27f438 100644
--- a/en/application-dev/media/audio-effect-management.md
+++ b/en/application-dev/media/audio-effect-management.md
@@ -91,7 +91,7 @@ Enable the default system audio effect.
## Obtaining the Global Audio Effect Mode
-You can obtain the global audio effect mode corresponding to a specific audio content type (specified by **ContentType**) and audio stream usage (specified by **StreamUsage**).
+You can obtain the global audio effect mode corresponding to a specific audio stream usage (specified by **StreamUsage**).
For an audio playback application, pay attention to the audio effect mode used by the audio stream of the application and perform corresponding operations. For example, for a music application, select the audio effect mode for the music scenario. Before obtaining the global audio effect mode, call **getStreamManager()** to create an **AudioStreamManager** instance.
### Creating an AudioStreamManager Instance
@@ -107,7 +107,7 @@ Create an **AudioStreamManager** instance. Before using **AudioStreamManager** A
### Querying the Audio Effect Mode of the Corresponding Scenario
```js
- audioStreamManager.getAudioEffectInfoArray(audio.ContentType.CONTENT_TYPE_MUSIC, audio.StreamUsage.STREAM_USAGE_MEDIA, async (err, audioEffectInfoArray) => {
+ audioStreamManager.getAudioEffectInfoArray(audio.StreamUsage.STREAM_USAGE_MEDIA, async (err, audioEffectInfoArray) => {
if (err) {
console.error('Failed to get effect info array');
return;
diff --git a/en/application-dev/media/audio-encoding.md b/en/application-dev/media/audio-encoding.md
index df2a0ace83f52fdbf1a9ae002dc6dae639088e4d..df7c4f51023a915583b44a3e8260593a2b64d546 100644
--- a/en/application-dev/media/audio-encoding.md
+++ b/en/application-dev/media/audio-encoding.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,169 +40,161 @@ 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 inQueue_;
- std::queue outQueue_;
- std::queue inBufferQueue_;
- std::queue outBufferQueue_;
- std::queue 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 inQueue_;
+ std::queue outQueue_;
+ std::queue inBufferQueue_;
+ std::queue outBufferQueue_;
+ std::queue 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:
- - **OnError**, a callback used to report a codec operation error
- - **OnOutputFormatChanged**, a callback used to report a codec stream change, for example, audio channel change
- - **OnInputBufferAvailable**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
- - **OnOutputBufferAvailable**, a callback used to report output data generated, which means that encoding is complete
+ - **OH_AVCodecOnError**, a callback used to report a codec operation error
+ - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
+ - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
+ - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that encoding is complete
You need to process the callback functions to ensure that the encoder runs properly.
- ```cpp
- // Set the OnError callback function.
- static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
- {
- (void)codec;
- (void)errorCode;
- (void)userData;
- }
- // Set the OnOutputFormatChanged callback function.
- static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
- {
- (void)codec;
- (void)format;
- (void)userData;
- }
- // Set the OnInputBufferAvailable callback function, which is used to send the input PCM data to the InputBuffer queue.
- static void OnInputBufferAvailable(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(userData);
- cout << "OnInputBufferAvailable received, index:" << index << endl;
- unique_lock lock(signal->inMutex_);
- signal->inQueue_.push(index);
- signal->inBufferQueue_.push(data);
- signal->inCond_.notify_all();
- }
- // Set the OnOutputBufferAvailable callback function, which is used to send the encoded stream to the OutputBuffer queue.
- static void OnOutputBufferAvailable(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 the OutputQueue.
- // The encoded data is sent to the OutputBuffer queue.
- AEncSignal *signal = static_cast(userData);
- unique_lock lock(signal->outMutex_);
- signal->outQueue_.push(index);
- signal->outBufferQueue_.push(data);
- if (attr) {
- signal->attrQueue_.push(*attr);
- }
- }
- OH_AVCodecAsyncCallback cb = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
- // 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(userData);
+ unique_lock 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(userData);
+ unique_lock 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();
- // 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();
- 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();
+ // 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();
+ 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.
@@ -214,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(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(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.
@@ -283,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()**.
@@ -335,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
diff --git a/en/application-dev/media/audio-playback-overview.md b/en/application-dev/media/audio-playback-overview.md
index 5ef7a6f9c4d08719a71c9e07f34fa1104802fcc6..767f3dd775546f58844885406bc4816dc82a2eb6 100644
--- a/en/application-dev/media/audio-playback-overview.md
+++ b/en/application-dev/media/audio-playback-overview.md
@@ -20,6 +20,6 @@ To enable your application to play a video in the background or when the screen
1. The application is registered with the system for unified management through the **AVSession** APIs. Otherwise, the playback will be forcibly stopped when the application switches to the background. For details, see [AVSession Development](avsession-overview.md).
-2. The application must request a continuous task to prevent from being suspended. For details, see [Continuous Task Development](../task-management/continuous-task-dev-guide.md).
+2. The application must request a continuous task to prevent from being suspended. For details, see [Continuous Task](../task-management/continuous-task.md).
If the playback is interrupted when the application switches to the background, you can view the log to see whether the application has requested a continuous task. If the application has requested a continuous task, there is no log recording **pause id**; otherwise, there is a log recording **pause id**.
diff --git a/en/application-dev/media/avscreen-capture.md b/en/application-dev/media/avscreen-capture.md
new file mode 100644
index 0000000000000000000000000000000000000000..b435311c0697c90f2ae1e59d1235caecd7a9ef26
--- /dev/null
+++ b/en/application-dev/media/avscreen-capture.md
@@ -0,0 +1,236 @@
+# 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. 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, ×tamp, &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, ×tamp, &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;
+}
+```
diff --git a/en/application-dev/media/avsession-overview.md b/en/application-dev/media/avsession-overview.md
index 766e642eebc2ba861bf6aceca5f9ea702f99d74f..619c37bdc97999dd35ffbc3cec6426cd00713906 100644
--- a/en/application-dev/media/avsession-overview.md
+++ b/en/application-dev/media/avsession-overview.md
@@ -4,7 +4,7 @@ The Audio and Video Session (AVSession) service is used to manage the playback b
Audio and video applications access the AVSession service and send application data (for example, a song that is being played and playback state) to it. Through a controller, the user can choose another application or device to continue the playback. If an application does not access the AVSession service, its playback will be forcibly interrupted when it switches to the background.
-To implement background playback, you must request a continuous task to prevent the task from being suspended. For details, see [Continuous Task Development](../task-management/continuous-task-dev-guide.md).
+To implement background playback, you must request a continuous task to prevent the task from being suspended. For details, see [Continuous Task](../task-management/continuous-task.md).
## Basic Concepts
diff --git a/en/application-dev/media/camera-performance-improvement.md b/en/application-dev/media/camera-performance-improvement.md
new file mode 100644
index 0000000000000000000000000000000000000000..f5bdeb76c4abdb54aa15e113e4ce950ae9ea6539
--- /dev/null
+++ b/en/application-dev/media/camera-performance-improvement.md
@@ -0,0 +1,168 @@
+# 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 **\**.
+
+The deferred stream configuration feature decouples stream configuration and start from the surface. Before the **\** 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.
+
+
+
+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\ | 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\ | 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.
+
+
+
+```js
+import camera from '@ohos.multimedia.camera';
+
+function async preview(context: Context, cameraInfo: camera.Device, previewProfile: camera.Profile, photoProfile: camera.Profile, surfaceId: string): Promise {
+ 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\): 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.
+
+
+
+```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.
+
+
+
+### 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.
+
+
+
+- **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}`)
+ }
+ }
+ ```
diff --git a/en/application-dev/media/camera-recording-case.md b/en/application-dev/media/camera-recording-case.md
index e92b8d80d5289071b507f59dcee1389733c498bb..783c35ab1f93158e511f9765b0f76c703e95e9ca 100644
--- a/en/application-dev/media/camera-recording-case.md
+++ b/en/application-dev/media/camera-recording-case.md
@@ -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 }
}
diff --git a/en/application-dev/media/camera-recording.md b/en/application-dev/media/camera-recording.md
index 9d872d6b323f84718ac045be83cebda268b08d8c..88f5f6913cebf9b20c3adce3c0da9d849764651a 100644
--- a/en/application-dev/media/camera-recording.md
+++ b/en/application-dev/media/camera-recording.md
@@ -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) {
diff --git a/en/application-dev/media/figures/audio-decode.png b/en/application-dev/media/figures/audio-decode.png
index f76febe618c2529b3530436ddab6cb954a42d3b2..388cc259a9500e7b0db7c4d6f9a91f15449de69c 100644
Binary files a/en/application-dev/media/figures/audio-decode.png and b/en/application-dev/media/figures/audio-decode.png differ
diff --git a/en/application-dev/media/figures/audio-encode.png b/en/application-dev/media/figures/audio-encode.png
index 06be355cc372f7d8fc5614268f4358bbcea1e1a3..f36aca830c3d8831f53cfec1deb77ddf56d0ccac 100644
Binary files a/en/application-dev/media/figures/audio-encode.png and b/en/application-dev/media/figures/audio-encode.png differ
diff --git a/en/application-dev/media/figures/deferred-surface-scene.png b/en/application-dev/media/figures/deferred-surface-scene.png
new file mode 100644
index 0000000000000000000000000000000000000000..fac0141a196abf281b41b4df7b40aff15a95fe12
Binary files /dev/null and b/en/application-dev/media/figures/deferred-surface-scene.png differ
diff --git a/en/application-dev/media/figures/deferred-surface-sequence-diagram.png b/en/application-dev/media/figures/deferred-surface-sequence-diagram.png
new file mode 100644
index 0000000000000000000000000000000000000000..14f27fe8bcaf190b60da741bdd9092bc0929e1a1
Binary files /dev/null and b/en/application-dev/media/figures/deferred-surface-sequence-diagram.png differ
diff --git a/en/application-dev/media/figures/prelaunch-scene.png b/en/application-dev/media/figures/prelaunch-scene.png
new file mode 100644
index 0000000000000000000000000000000000000000..25139365b0a66170bc7d9e4bdff41c8aeaa023fd
Binary files /dev/null and b/en/application-dev/media/figures/prelaunch-scene.png differ
diff --git a/en/application-dev/media/figures/prelaunch-sequence-diagram.png b/en/application-dev/media/figures/prelaunch-sequence-diagram.png
new file mode 100644
index 0000000000000000000000000000000000000000..b28c3ffdd6fa7aeb2c4d3d22a267a982504370cf
Binary files /dev/null and b/en/application-dev/media/figures/prelaunch-sequence-diagram.png differ
diff --git a/en/application-dev/media/figures/quick-thumbnail-sequence-diagram.png b/en/application-dev/media/figures/quick-thumbnail-sequence-diagram.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c05f247683566c2e37b3a2b8797e7e487b3376f
Binary files /dev/null and b/en/application-dev/media/figures/quick-thumbnail-sequence-diagram.png differ
diff --git a/en/application-dev/media/figures/video-decode.png b/en/application-dev/media/figures/video-decode.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb3fd0f7351359d83572f89605c5c99a306740ba
Binary files /dev/null and b/en/application-dev/media/figures/video-decode.png differ
diff --git a/en/application-dev/media/figures/video-encode.png b/en/application-dev/media/figures/video-encode.png
new file mode 100644
index 0000000000000000000000000000000000000000..4f29b68813155f2b79b3f5cd6d8756f9c28bcfd5
Binary files /dev/null and b/en/application-dev/media/figures/video-encode.png differ
diff --git a/en/application-dev/media/using-avplayer-for-playback.md b/en/application-dev/media/using-avplayer-for-playback.md
index 9af55fb71b489f7b3ece342969c72d18ed90eaab..e5cd19b6c1077d9c73660087d751b48a47601e12 100644
--- a/en/application-dev/media/using-avplayer-for-playback.md
+++ b/en/application-dev/media/using-avplayer-for-playback.md
@@ -2,7 +2,7 @@
The AVPlayer is used to play raw media assets in an end-to-end manner. In this topic, you will learn how to use the AVPlayer to play a complete piece of music.
-If you want the application to continue playing the music in the background or when the screen is off, you must use the [AVSession](avsession-overview.md) and [continuous task](../task-management/continuous-task-dev-guide.md) to prevent the playback from being forcibly interrupted by the system.
+If you want the application to continue playing the music in the background or when the screen is off, you must use the [AVSession](avsession-overview.md) and [continuous task](../task-management/continuous-task.md) to prevent the playback from being forcibly interrupted by the system.
The full playback process includes creating an **AVPlayer** instance, setting the media asset to play, setting playback parameters (volume, speed, and focus mode), controlling playback (play, pause, seek, and stop), resetting the playback configuration, and releasing the instance.
@@ -40,7 +40,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).
>
diff --git a/en/application-dev/media/using-ohaudio-for-playback.md b/en/application-dev/media/using-ohaudio-for-playback.md
index d63468342a25627e95e3e82b210b36a3dedff685..a90cfe257371c7a0b35c2e2f5b843a69fe1ac155 100644
--- a/en/application-dev/media/using-ohaudio-for-playback.md
+++ b/en/application-dev/media/using-ohaudio-for-playback.md
@@ -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);
+```
diff --git a/en/application-dev/media/video-decoding.md b/en/application-dev/media/video-decoding.md
index 7e1dd04c05bb519b1c16cb480050f4625967a474..a267a9195cade7bcb44eecbbeba30450d686eb4f 100644
--- a/en/application-dev/media/video-decoding.md
+++ b/en/application-dev/media/video-decoding.md
@@ -15,21 +15,24 @@ Video software decoding and hardware decoding are different. When a decoder is c
Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API reference.
+The figure below shows the call relationship of video decoding.
+
+
+
1. Create a decoder instance.
You can create a decoder by name or MIME type.
``` c++
- // Create a decoder by name.
+ // To create a decoder by name, call OH_AVCapability_GetName to obtain the codec names available and then call OH_VideoDecoder_CreateByName. If your application has special requirements, for example, expecting a decoder that supports a certain resolution, you can call OH_AVCodec_GetCapability to query the capability first.
OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false);
const char *name = OH_AVCapability_GetName(capability);
- OH_AVCodec *videoDec = OH_VideoDecoder_CreateByName(name); // name:"OH.Media.Codec.Decoder.Video.AVC"
+ OH_AVCodec *videoDec = OH_VideoDecoder_CreateByName(name);
```
```c++
// Create a decoder by MIME type.
- // Create an H.264 decoder for software/hardware decoding.
+ // Create an H.264 decoder for software/hardware decoding. The system creates the most appropriate decoder if multiple decoders are available.
OH_AVCodec *videoDec = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
- // Create a decoder by MIME type.
// Create an H.265 decoder for hardware decoding.
OH_AVCodec *videoDec = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_HEVC);
```
@@ -54,30 +57,32 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
- - **OnError**, a callback used to report a codec operation error
- - **OnOutputFormatChanged**, a callback used to report a codec stream change, for example, stream width or height change.
- - **OnInputBufferAvailable**, a callback used to report input data required, which means that the decoder is ready for receiving data
- - **OnOutputBufferAvailable**, a callback used to report output data generated, which means that decoding is complete (Note: The **data** parameter in the callback function is empty in surface output mode.)
+ - **OH_AVCodecOnError**, a callback used to report a codec operation error
+ - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, stream width or height change.
+ - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the decoder is ready for receiving data
+ - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that decoding is complete (Note: The **data** parameter in the callback function is empty in surface output mode.)
You need to process the callback functions to ensure that the decoder runs properly.
``` c++
- // Set the OnError callback function.
+ // Implement the OH_AVCodecOnError callback function.
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
(void)codec;
(void)errorCode;
(void)userData;
}
- // Set the OnOutputFormatChanged callback function.
- static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, 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;
}
- // Set the OnInputBufferAvailable callback function, which is used to obtain the input frame information.
- static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
+
+ // Implement the OH_AVCodecOnNeedInputData callback function.
+ static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
{
(void)codec;
VDecSignal *signal_ = static_cast(userData);
@@ -88,8 +93,9 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
signal_->inBufferQueue_.push(data);
signal_->inCond_.notify_all();
}
- // Set the OnOutputBufferAvailable callback function, which is used to obtain the output frame information.
- static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
+
+ // 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;
@@ -102,7 +108,7 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
signal_->attrQueue_.push(*attr);
signal_->outCond_.notify_all();
}
- OH_AVCodecAsyncCallback cb = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
+ OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
// Set the asynchronous callbacks.
int32_t ret = OH_VideoDecoder_SetCallback(videoDec, cb, signal_);
```
@@ -146,7 +152,7 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
```
5. (Optional) Configure the surface parameters of the decoder. This step is required only when the surface is used.
-
+
``` c++
OH_AVFormat *format = OH_AVFormat_Create();
// Configure the display rotation angle.
@@ -179,7 +185,7 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
``` c++
// Configure the buffer information.
OH_AVCodecBufferAttr info;
- // Call av_packet_alloc to initialize and return a container packet.
+ // Call av_packet_alloc of FFmpeg to initialize and return a container packet.
AVPacket pkt = av_packet_alloc();
// Configure the input size, offset, and timestamp of the buffer.
info.size = pkt->size;
@@ -208,9 +214,9 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
```
9. (Optional) Call **OH_VideoDecoder_Flush()** to refresh the decoder.
-
+
After **OH_VideoDecoder_Flush()** is called, the decoder remains in the running state, but the current queue is cleared and the buffer storing the decoded data is freed.
-
+
To continue decoding, you must call **OH_VideoDecoder_Start()** again.
``` c++
@@ -225,7 +231,7 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
```
10. (Optional) Call **OH_VideoDecoder_Reset()** to reset the decoder.
-
+
After **OH_VideoDecoder_Reset()** is called, the decoder returns to the initialized state. To continue decoding, you must call **OH_VideoDecoder_Configure()** and then **OH_VideoDecoder_Start()**.
``` c++
@@ -240,7 +246,7 @@ Read [VideoDecoder](../reference/native-apis/_video_decoder.md) for the API refe
```
11. Call **OH_VideoDecoder_Stop()** to stop the decoder.
-
+
``` c++
int32_t ret;
// Stop the decoder.
diff --git a/en/application-dev/media/video-encoding.md b/en/application-dev/media/video-encoding.md
index 410922d95b5e66cb2ceab1aee20640a13283d54b..fee759c06f0baaf2c57ee0a4068a68af2048e5ed 100644
--- a/en/application-dev/media/video-encoding.md
+++ b/en/application-dev/media/video-encoding.md
@@ -29,14 +29,19 @@ For details about the development procedure, see [Buffer Input](#buffer-input) a
Read [VideoEncoder](../reference/native-apis/_video_encoder.md) for the API reference.
+The figure below shows the call relationship of video encoding.
+
+
+
### Buffer Input
The following walks you through how to implement the entire video encoding process in buffer input mode. It uses the YUV file input and H.264 encoding format as an example.
+
Currently, the **VideoEncoder** module supports only data transferring in asynchronous mode.
1. Create an encoder instance.
- You can create an encoder by name or Multipurpose Internet Mail Extensions (MIME) type.
+ You can create an encoder by name or MIME type.
``` c++
// To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
@@ -58,15 +63,15 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
- - **OnError**, a callback used to report a codec operation error
- - **OnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
- - **OnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
- - **OnNeedOutputData**, a callback used to report output data generated, which means that encoding is complete
+ - **OH_AVCodecOnError**, a callback used to report a codec operation error
+ - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
+ - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
+ - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that encoding is complete
You need to process the callback functions to ensure that the encoder runs properly.
``` c++
- // Set the OnError callback function.
+ // Implement the OH_AVCodecOnError callback function.
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
(void)codec;
@@ -74,7 +79,7 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
(void)userData;
}
- // Set the OnStreamChanged callback function.
+ // Implement the OH_AVCodecOnStreamChanged callback function.
static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
(void)codec;
@@ -82,7 +87,7 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
(void)userData;
}
- // Set the OnNeedInputData callback function, which is used to send an input frame to the data queue.
+ // Implement the OH_AVCodecOnNeedInputData callback function.
static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem, void *userData)
{
(void)userData;
@@ -92,8 +97,8 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
// 7. Write the stream to encode.
// 8. Notify the encoder of EOS.
}
-
- // Set the OnNeedOutputData callback function, which is used to send an encoded frame to the output queue.
+
+ // Implement the OH_AVCodecOnNewOutputData callback function.
static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem,
OH_AVCodecBufferAttr *attr, void *userData)
{
@@ -259,7 +264,7 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
9. Call **OH_VideoEncoder_FreeOutputData()** to output the encoded frames.
- In the code snippet below, the following parameters are used:
+ In the code snippet below, the following parameters are used:
- **index**: index of the data queue, which is passed in by the callback function **OnNeedOutputData**.
- **attr**: buffer storing the output data, which is passed in by the callback function **OnNeedOutputData**.
- **mem**: parameter passed in by the callback function **OnNeedOutputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
@@ -424,9 +429,9 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
Currently, the following options must be configured for all supported formats: video frame width, video frame height, and video pixel format.
In the code snippet below, the following data is used:
- - **DEFAULT_WIDTH**: 320 pixels
- - **DEFAULT_HEIGHT**: 240 pixels
- - **DEFAULT_PIXELFORMAT**: **VideoPixelFormat::YUV420P** (the pixel format of the YUV file is YUV420P)
+ - **DEFAULT_WIDTH**: 320 pixels
+ - **DEFAULT_HEIGHT**: 240 pixels
+ - **DEFAULT_PIXELFORMAT**: **VideoPixelFormat::YUV420P** (the pixel format of the YUV file is YUV420P)
``` c++
// (Mandatory) Configure the video frame width.
@@ -547,7 +552,7 @@ Currently, the **VideoEncoder** module supports only data transferring in asynch
10. Call **OH_VideoEncoder_FreeOutputData()** to output the encoded frames.
- In the code snippet below, the following parameters are used:
+ In the code snippet below, the following parameters are used:
- **index**: index of the data queue, which is passed in by the callback function **OnNeedOutputData**.
- **attr**: buffer storing the output data, which is passed in by the callback function **OnNeedOutputData**.
- **mem**: parameter passed in by the callback function **OnNeedOutputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
diff --git a/en/application-dev/media/video-playback.md b/en/application-dev/media/video-playback.md
index f745f2f25120f7068de6634af56aa1f443c5b5d9..40c754219cf35dc234be37635fcb8a27bfb86027 100644
--- a/en/application-dev/media/video-playback.md
+++ b/en/application-dev/media/video-playback.md
@@ -6,7 +6,7 @@ OpenHarmony provides two solutions for video playback development:
- component: encapsulates basic video playback capabilities. It can be used to play video files after the data source and basic information are set. However, its scalability is poor. This component is provided by ArkUI. For details about how to use this component for video playback development, see [Video Component](../ui/arkts-common-components-video-player.md).
-In this topic, you will learn how to use the AVPlayer to develop a video playback service that plays a complete video file. If you want the application to continue playing the video in the background or when the screen is off, you must use the [AVSession](avsession-overview.md) and [continuous task](../task-management/continuous-task-dev-guide.md) to prevent the playback from being forcibly interrupted by the system.
+In this topic, you will learn how to use the AVPlayer to develop a video playback service that plays a complete video file. If you want the application to continue playing the video in the background or when the screen is off, you must use the [AVSession](avsession-overview.md) and [continuous task](../task-management/continuous-task.md) to prevent the playback from being forcibly interrupted by the system.
## Development Guidelines
@@ -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).
>
diff --git a/en/application-dev/napi/Readme-EN.md b/en/application-dev/napi/Readme-EN.md
index ad566d55f740fd7ada74fe22b95e0f1824271c2d..f2012a21898bb8c38e6b78e1dd65ab617bb6e0b5 100644
--- a/en/application-dev/napi/Readme-EN.md
+++ b/en/application-dev/napi/Readme-EN.md
@@ -1,11 +1,23 @@
# Native APIs
- [Using Native APIs in Application Projects](napi-guidelines.md)
-- [Drawing Development](drawing-guidelines.md)
-- [Raw File Development](rawfile-guidelines.md)
-- [Native Window Development](native-window-guidelines.md)
-- [Using MindSpore Lite for Model Inference](mindspore-lite-guidelines.md)
-- [Using MindSpore Lite for Offline Model Conversion and Inference](mindspore-lite-offline-model-guidelines.md)
-- [Connecting the Neural Network Runtime to an AI Inference Framework](neural-network-runtime-guidelines.md)
-- [Purgeable Memory Development](purgeable-memory-guidelines.md)
-- [USB DDK Development](usb-ddk-guidelines.md)
\ No newline at end of file
+- Graphics
+ - [Drawing Development](drawing-guidelines.md)
+ - [NativeBuffer Development](native-buffer-guidelines.md)
+ - [NativeImage Development](native-image-guidelines.md)
+ - [NativeVsync Development](native-vsync-guidelines.md)
+ - [NativeWindow Development](native-window-guidelines.md)
+ - [Vulkan Development](vulkan-guidelines.md)
+- Resource Management
+ - [Raw File Development](rawfile-guidelines.md)
+- AI
+ - [Using MindSpore Lite for Model Inference](mindspore-lite-guidelines.md)
+ - [Using MindSpore Lite for Offline Model Conversion and Inference](mindspore-lite-offline-model-guidelines.md)
+ - [Connecting the Neural Network Runtime to an AI Inference Framework](neural-network-runtime-guidelines.md)
+- Memory Management
+ - [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)
+
diff --git a/en/application-dev/napi/figures/onDestroy.png b/en/application-dev/napi/figures/onDestroy.png
new file mode 100644
index 0000000000000000000000000000000000000000..41f10a3a0a1ecafb673f5013199977a42bc9b531
Binary files /dev/null and b/en/application-dev/napi/figures/onDestroy.png differ
diff --git a/en/application-dev/napi/figures/onLoad.png b/en/application-dev/napi/figures/onLoad.png
new file mode 100644
index 0000000000000000000000000000000000000000..361cd48e2ddd5e14b86644628c09874d411c37f9
Binary files /dev/null and b/en/application-dev/napi/figures/onLoad.png differ
diff --git a/en/application-dev/napi/native-buffer-guidelines.md b/en/application-dev/napi/native-buffer-guidelines.md
index b45c43f77e6d63aac676327bc971d9eeb0609259..fae8927caa9563c9fd459906d9fb9ecf2e166297 100644
--- a/en/application-dev/napi/native-buffer-guidelines.md
+++ b/en/application-dev/napi/native-buffer-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
@@ -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.
diff --git a/en/application-dev/napi/native-image-guidelines.md b/en/application-dev/napi/native-image-guidelines.md
index 10142f438059908cef4320b5d01e2029cf6cfe16..46518e0985b2b8ab8403456fced4d16f69b1fcb9 100644
--- a/en/application-dev/napi/native-image-guidelines.md
+++ b/en/application-dev/napi/native-image-guidelines.md
@@ -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
@@ -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(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(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.
diff --git a/en/application-dev/napi/native-relational-store-guidelines.md b/en/application-dev/napi/native-relational-store-guidelines.md
new file mode 100644
index 0000000000000000000000000000000000000000..b2f545c5c9989e1e1cf63e6a6ab0030b09bceed4
--- /dev/null
+++ b/en/application-dev/napi/native-relational-store-guidelines.md
@@ -0,0 +1,182 @@
+# 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);
+ ```
diff --git a/en/application-dev/napi/native-vsync-guidelines.md b/en/application-dev/napi/native-vsync-guidelines.md
index 548a791e97ee75a1ee4ad83123893c5495181b59..f43495857483fc529ce03b565011a59e98fc07a7 100644
--- a/en/application-dev/napi/native-vsync-guidelines.md
+++ b/en/application-dev/napi/native-vsync-guidelines.md
@@ -6,12 +6,12 @@ The **NativeVSync** module is used to obtain virtual synchronization (VSync) sig
## Available APIs
-| API| Description:|
+| API| Description|
| -------- | -------- |
-| OH_NativeVSync_Create (const char \*name, unsigned int length) | Creates an **OH_NativeVSync** instance. A new **OH_NativeVSync** instance is created each time this function is called.|
-| OH_NativeVSync_Destroy (OH_NativeVSync \*nativeVsync) | Destroys an **OH_NativeVSync** instance.|
-| OH_NativeVSync_FrameCallback (long long timestamp, void \*data) | Sets a callback function. **timestamp** indicates the timestamp, and **data** indicates the input parameter of the callback function. |
-| OH_NativeVSync_RequestFrame (OH_NativeVSync \*nativeVsync, OH_NativeVSync_FrameCallback callback, void \*data) | Requests the next VSync signal. When the signal arrives, a callback function is invoked.|
+| OH_NativeVSync_Create (const char \*name, unsigned int length) | Creates an **OH_NativeVSync** instance. A new **OH_NativeVSync** instance is created each time this function is called.|
+| OH_NativeVSync_Destroy (OH_NativeVSync \*nativeVsync) | Destroys an **OH_NativeVSync** instance.|
+| OH_NativeVSync_FrameCallback (long long timestamp, void \*data) | Sets a callback function. **timestamp** indicates the timestamp, and **data** indicates the input parameter of the callback function.|
+| OH_NativeVSync_RequestFrame (OH_NativeVSync \*nativeVsync, OH_NativeVSync_FrameCallback callback, void \*data) | Requests the next VSync signal. When the signal arrives, a callback function is invoked.|
For details about the APIs, see [native_vsync](../reference/native-apis/_native_vsync.md).
@@ -19,6 +19,13 @@ For details about the APIs, see [native_vsync](../reference/native-apis/_native_
The following steps describe how to use the native APIs provided by **NativeVSync** to create and destroy an **OH_NativeVSync** instance and set the VSync callback function.
+**Adding Dynamic Link Libraries**
+
+Add the following library to **CMakeLists.txt**:
+```txt
+libnative_vsync.so
+```
+
**Header File**
```c++
#include
@@ -33,12 +40,12 @@ The following steps describe how to use the native APIs provided by **NativeVSyn
std::cout << "OnVSync: " << timestamp << std::endl;
}
OH_NativeVSync_FrameCallback callback = OnVSync; // The callback function must be of the OH_NativeVSync_FrameCallback type.
- ```
+ ```
2. Create an **OH_NativeVSync** instance.
```c++
char name[] = "hello_vsync";
OH_NativeVSync* nativeVSync = OH_NativeVSync_Create(name, strlen(name));
- ```
+ ```
3. Set the VSync callback function through the **OH_NativeVSync** instance.
```c++
diff --git a/en/application-dev/napi/native-window-guidelines.md b/en/application-dev/napi/native-window-guidelines.md
index 4f39be0a9b311d28b1a6551eac728484893a948f..5c5a62ab3d256689d1d467595797e3f2c605b679 100644
--- a/en/application-dev/napi/native-window-guidelines.md
+++ b/en/application-dev/napi/native-window-guidelines.md
@@ -11,11 +11,11 @@ The following scenarios are common for NativeWindow development:
## Available APIs
-| API| Description|
+| API| Description|
| -------- | -------- |
-| OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | Requests an **OHNativeWindowBuffer** through an **OHNativeWindow** instance for content production.|
-| OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | Flushes the **OHNativeWindowBuffer** filled with the content to the buffer queue through an **OHNativeWindow** instance for content consumption.|
-| OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | Sets or obtains the attributes of an **OHNativeWindow**, including the width, height, and content format.|
+| OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | Requests an **OHNativeWindowBuffer** through an **OHNativeWindow** instance for content production.|
+| OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | Flushes the **OHNativeWindowBuffer** filled with the content to the buffer queue through an **OHNativeWindow** instance for content consumption.|
+| OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | Sets or obtains the attributes of an **OHNativeWindow**, including the width, height, and content format.|
For details about the APIs, see [native_window](../reference/native-apis/_native_window.md).
@@ -23,81 +23,88 @@ For details about the APIs, see [native_window](../reference/native-apis/_native
The following describes how to use the native APIs provided by **NativeWindow** to request a graphics buffer, write the produced graphics content to the buffer, and flush the buffer to the graphics queue.
+**Adding Dynamic Link Libraries**
+
+Add the following libraries to **CMakeLists.txt**:
+```txt
+libace_ndk.z.so
+libnative_window.so
+```
+
**Header File**
```c++
+#include
#include
```
-1. Obtain an **OHNativeWindow** instance, which can be obtained by running the APIs provided by [OH_NativeXComponent_Callback](../reference/native-apis/_o_h___native_x_component___callback.md).
- 1. Define **XComponent** in an .ets file.
+1. Obtain an **OHNativeWindow** instance.
+
+ You can call the APIs provided by [OH_NativeXComponent_Callback](../reference/native-apis/_o_h___native_x_component___callback.md) to obtain an **OHNativeWindow** instance. An example code snippet is provided below. For details about how to use the **\**, see [XComponent Development](xcomponent-guidelines.md).
+ 1. Add an **\** to the .ets file.
```ts
- XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'nativerender'})
- .onLoad((context) => {
- this.context = context;
- })
- .onDestroy(() => {
- })
+ XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'entry'})
+ .width(360)
+ .height(360)
+ ```
+ 2. Obtain **NativeXComponent** at the native C++ layer.
+ ```c++
+ napi_value exportInstance = nullptr;
+ // Parse the attribute of the wrapped NativeXComponent pointer.
+ napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ // Use the napi_unwrap API to parse the NativeXComponent instance pointer.
+ napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent));
+ ```
+ 3. Define **OH_NativeXComponent_Callback**.
+ ```c++
+ // Define the callback.
+ void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window)
+ {
+ // Obtain an OHNativeWindow instance.
+ OHNativeWindow* nativeWindow = static_cast(window);
+ // ...
+ }
+ void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window)
+ {
+ // Obtain an OHNativeWindow instance.
+ OHNativeWindow* nativeWindow = static_cast(window);
+ // ...
+ }
+ void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window)
+ {
+ // Obtain an OHNativeWindow instance.
+ OHNativeWindow* nativeWindow = static_cast(window);
+ // ...
+ }
+ void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
+ {
+ // Obtain an OHNativeWindow instance.
+ OHNativeWindow* nativeWindow = static_cast(window);
+ // ...
+ }
+ ```
+ ```c++
+ // Initialize OH_NativeXComponent_Callback.
+ OH_NativeXComponent_Callback callback;
+ callback.OnSurfaceCreated = OnSurfaceCreatedCB;
+ callback.OnSurfaceChanged = OnSurfaceChangedCB;
+ callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
+ callback.DispatchTouchEvent = DispatchTouchEventCB;
```
- 2. Obtain **NativeXComponent** at the native C++ layer.
- ```c++
- napi_value exportInstance = nullptr;
- napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
-
- OH_NativeXComponent *nativeXComponent = nullptr;
- napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent));
-
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);
- ```
- 3. Define **OH_NativeXComponent_Callback**.
- ```c++
- // Define the callback.
- void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window)
- {
- // Obtain an OHNativeWindow instance.
- OHNativeWindow* nativeWindow = window;
- // ...
- }
- void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window)
- {
- // Obtain an OHNativeWindow instance.
- OHNativeWindow* nativeWindow = window;
- // ...
- }
- void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window)
- {
- // Obtain an OHNativeWindow instance.
- OHNativeWindow* nativeWindow = window;
- // ...
- }
- void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
- {
- // Obtain an OHNativeWindow instance.
- OHNativeWindow* nativeWindow = window;
- // ...
- }
- ```
- ```c++
- // Initialize OH_NativeXComponent_Callback.
- OH_NativeXComponent_Callback callback_;
- callback_->OnSurfaceCreated = OnSurfaceCreatedCB;
- callback_->OnSurfaceChanged = OnSurfaceChangedCB;
- callback_->OnSurfaceDestroyed = OnSurfaceDestroyedCB;
- callback_->DispatchTouchEvent = DispatchTouchEventCB;
- ```
4. Register **OH_NativeXComponent_Callback** with **NativeXComponent**.
- ```c++
- OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback_);
- ```
+ ```c++
+ // Register the callback.
+ OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
+ ```
2. Set the attributes of an **OHNativeWindowBuffer** by using **OH_NativeWindow_NativeWindowHandleOpt**.
```c++
// Set the width and height of the OHNativeWindowBuffer.
- code = SET_BUFFER_GEOMETRY;
+ int32_t code = SET_BUFFER_GEOMETRY;
int32_t width = 0x100;
int32_t height = 0x100;
- ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
+ // The nativeWindow instance is obtained from the callback in the previous step.
+ int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
// Set the step of the OHNativeWindowBuffer.
code = SET_STRIDE;
int32_t stride = 0x8;
@@ -109,18 +116,27 @@ The following describes how to use the native APIs provided by **NativeWindow**
OHNativeWindowBuffer* buffer = nullptr;
int fenceFd;
// Obtain the OHNativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer.
- OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer, &fenceFd);
- // Obtain the buffer handle by calling OH_NativeWindow_GetNativeBufferHandleFromNative.
- BufferHandle* bufferHandle = OH_NativeWindow_GetNativeBufferHandleFromNative(buffer);
+ OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
+ // Obtain the buffer handle by calling OH_NativeWindow_GetBufferHandleFromNative.
+ BufferHandle* bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
+ ```
+
+4. Map memory.
+ ```c++
+ #include
+
+ // Use mmap() to obtain the memory virtual address of buffer handle.
+ void* mappedAddr = mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
+ if (mappedAddr == MAP_FAILED) {
+ // mmap failed
+ }
```
-4. Write the produced content to the **OHNativeWindowBuffer**.
+5. Write the produced content to the **OHNativeWindowBuffer**.
```c++
- auto image = static_cast(buffer->sfbuffer->GetVirAddr());
static uint32_t value = 0x00;
value++;
-
- uint32_t *pixel = static_cast(image);
+ uint32_t *pixel = static_cast(mappedAddr); // Use the address obtained by mmap() to access the memory.
for (uint32_t x = 0; x < width; x++) {
for (uint32_t y = 0; y < height; y++) {
*pixel++ = value;
@@ -133,5 +149,13 @@ The following describes how to use the native APIs provided by **NativeWindow**
// Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the OHNativeWindowBuffer 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);
+ OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
+ ```
+6. Unmap memory.
+ ```c++
+ // Unmap the memory when the memory is no longer required.
+ int result = munmap(mappedAddr, bufferHandle->size);
+ if (result == -1) {
+ // munmap failed
+ }
```
diff --git a/en/application-dev/napi/neural-network-runtime-guidelines.md b/en/application-dev/napi/neural-network-runtime-guidelines.md
index 0c86fd05801197bdd63a885c2071f258687a768e..974ccc5bafbfe7169034924ba27d0eb3c91606a8 100644
--- a/en/application-dev/napi/neural-network-runtime-guidelines.md
+++ b/en/application-dev/napi/neural-network-runtime-guidelines.md
@@ -1,4 +1,4 @@
-# Connecting the Neural Network Runtime to an AI Inference Framework
+# Development Guide for Connecting the Neural Network Runtime to an AI Inference Framework
## When to Use
@@ -19,13 +19,14 @@ The environment requirements for the Neural Network Runtime are as follows:
- Development environment: Ubuntu 18.04 or later.
- Access device: a standard device running OpenHarmony. The built-in hardware accelerator driver has been connected to the Neural Network Runtime through an HDI API.
-The Neural Network Runtime is opened to external systems through OpenHarmony Native APIs. Therefore, you need to use the Native development suite of the OpenHarmony to compile Neural Network Runtime applications. You can download the **ohos-sdk** package of the corresponding version from [Daily Build](http://ci.openharmony.cn/dailys/dailybuilds) in the OpenHarmony community and then decompress the package to obtain the Native development suite of the corresponding platform. Take Linux as an example. The package of the Native development suite is named `native-linux-{version number}.zip`.
+The Neural Network Runtime is opened to external systems through OpenHarmony Native APIs. Therefore, you need to use the Native development suite of the OpenHarmony to compile Neural Network Runtime applications.
### Environment Setup
1. Start the Ubuntu server.
-2. Copy the downloaded package of the Native development suite to the root directory of the current user.
+2. Copy the package of the Native development suite to the root directory of the current user.
3. Decompress the package of the Native development suite.
+
```shell
unzip native-linux-{version number}.zip
```
@@ -470,22 +471,19 @@ The development process of the Neural Network Runtime consists of three phases:
> The IR graphs of the model need to be passed to the hardware driver layer, so that the HDI service compiles the IR graphs into a computing graph dedicated to hardware. The compilation process is time-consuming. The Neural Network Runtime supports the computing graph cache feature. It can cache the computing graphs compiled by the HDI service to the device storage. If the same model is compiled on the same acceleration chip next time, you can specify the cache path so that the Neural Network Runtime can directly load the computing graphs in the cache file, reducing the compilation time.
Check the cached files in the cache directory.
+
```shell
ls /data/local/tmp
```
The command output is as follows:
+
```text
# 0.nncache cache_info.nncache
```
If the cache is no longer used, manually delete the cache files.
+
```shell
rm /data/local/tmp/*nncache
```
-
-## Samples
-
-The following sample is provided to help you understand how to connect a third-party AI inference framework to the Neural Network Runtime:
-- [Development Guide for Connecting TensorFlow Lite to NNRt Delegate](https://gitee.com/openharmony/neural_network_runtime/tree/master/example/deep_learning_framework)
-
diff --git a/en/application-dev/napi/vulkan-guidelines.md b/en/application-dev/napi/vulkan-guidelines.md
index e55b53cd38d44fb5d5a893cdbc21d175b9b0c8df..6ce31b8e1339633bcaa45f47637204f3b4ecef84 100644
--- a/en/application-dev/napi/vulkan-guidelines.md
+++ b/en/application-dev/napi/vulkan-guidelines.md
@@ -18,6 +18,15 @@ For details about the APIs, see [Vulkan](../reference/native-lib/third_party_vul
The following steps illustrate how to create a **VkSurfaceKHR** instance.
+**Adding Dynamic Link Libraries**
+
+Add the following libraries to **CMakeLists.txt**:
+```txt
+libace_ndk.z.so
+libnative_window.so
+libvulkan.so
+```
+
**Header File**
```c++
#include
diff --git a/en/application-dev/napi/xcomponent-guidelines.md b/en/application-dev/napi/xcomponent-guidelines.md
new file mode 100644
index 0000000000000000000000000000000000000000..dd365dd461a3bf868451b047aecd1c8f68c5b390
--- /dev/null
+++ b/en/application-dev/napi/xcomponent-guidelines.md
@@ -0,0 +1,902 @@
+# XComponent Development
+
+## When to Use
+
+**NativeXComponent** provides an instance for the **\** at the native layer, which can be used as a bridge for binding with the **\** at the JS layer. The NDK APIs provided by the **\** depend on this instance. The provided APIs include those for obtaining a native window, obtaining the layout or event information of the **\**, registering the lifecycle callbacks of the **\**, and registering the callbacks for the touch, mouse, and key events of the **\**. You can use the provided APIs in the following scenarios:
+
+- Register the lifecycle and event callbacks of the **\**.
+- In these callbacks, you can initialize the environment, obtain the current state, and respond to various events.
+- Use the native window and EGL APIs to develop custom drawing content, and apply for and submit buffers to the graphics queue.
+
+## Available APIs
+
+| API| Description.|
+| -------- | -------- |
+|OH_NativeXComponent_GetXComponentId(OH_NativeXComponent* component, char* id, uint64_t* size)|Obtains the ID of the **\**.|
+|OH_NativeXComponent_GetXComponentSize(OH_NativeXComponent* component, const void* window, uint64_t* width, uint64_t* height)|Obtains the size of the surface held by the **\**.|
+|OH_NativeXComponent_GetXComponentOffset(OH_NativeXComponent* component, const void* window, double* x, double* y)|Obtains the offset of the surface held by the **\** relative to the upper left corner of the window.|
+|OH_NativeXComponent_GetTouchEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_TouchEvent* touchEvent)|Obtains the touch event triggered by the **\**.|
+|OH_NativeXComponent_GetTouchPointToolType(OH_NativeXComponent* component, uint32_t pointIndex, OH_NativeXComponent_TouchPointToolType* toolType)|Obtains the tool type of the **\** touch point.|
+|OH_NativeXComponent_GetTouchPointTiltX(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltX)|Obtains the tilt angle of the **\** touch point relative to the x-axis.|
+|OH_NativeXComponent_GetTouchPointTiltY(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltY)|Obtains the tilt angle of the **\** touch point relative to the y-axis.|
+|OH_NativeXComponent_GetMouseEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_MouseEvent* mouseEvent)|Obtains the mouse event triggered by the **\**.|
+|OH_NativeXComponent_RegisterCallback(OH_NativeXComponent* component, OH_NativeXComponent_Callback* callback)|Registers the lifecycle and touch event callback for this **OH_NativeXComponent** instance.|
+|OH_NativeXComponent_RegisterMouseEventCallback(OH_NativeXComponent* component, OH_NativeXComponent_MouseEvent_Callback* callback)|Registers the mouse event callback for this **OH_NativeXComponent** instance.|
+|OH_NativeXComponent_RegisterFocusEventCallback(OH_NativeXComponent* component, void (\*callback)(OH_NativeXComponent* component, void* window))|Registers the focus obtaining event callback function for this **OH_NativeXComponent** instance.|
+|OH_NativeXComponent_RegisterKeyEventCallback(OH_NativeXComponent* component, void (\*callback)(OH_NativeXComponent* component, void* window))|Registers the key event callback for this **OH_NativeXComponent** instance.|
+|OH_NativeXComponent_RegisterBlurEventCallback(OH_NativeXComponent* component, void (\*callback)(OH_NativeXComponent* component, void* window))|Registers the focus loss event callback for this **OH_NativeXComponent** instance.|
+|OH_NativeXComponent_GetKeyEvent(OH_NativeXComponent* component, OH_NativeXComponent_KeyEvent\** keyEvent)|Obtains the key event triggered by the **\**.|
+|OH_NativeXComponent_GetKeyEventAction(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyAction* action)|Obtains the action of a key event.|
+|OH_NativeXComponent_GetKeyEventCode(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyCode* code)|Obtains the key code value of a key event.|
+|OH_NativeXComponent_GetKeyEventSourceType(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_EventSourceType* sourceType)|Obtains the input source type of a key event.|
+|OH_NativeXComponent_GetKeyEventDeviceId(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* deviceId)|Obtains the device ID of a key event.|
+|OH_NativeXComponent_GetKeyEventTimestamp(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* timestamp)|Obtains the timestamp of a key event.|
+
+## Lifecycle Description
+
+You can use the **\** to develop EGL/OpenGL ES rendering by using the following code on the ArkTS side:
+
+```typescript
+XComponent({ id: 'xcomponentId1', type: 'surface', libraryname: 'nativerender' })
+ .onLoad((context) => {})
+ .onDestroy(() => {})
+```
+
+### **onLoad** Event
+
+Trigger time: when the surface of the **\** is ready.
+
+**context** parameter: where the native API exposed on the module is mounted. Its usage is similar to the usage of a **context** instance obtained after the module is directly loaded using **import context from "libnativerender.so"**.
+
+Time sequence: subject to the surface. The figure below shows the time sequence of the **onLoad** event and the **OnSurfaceCreated** event at the native layer.
+
+
+
+### **onDestroy** Event
+
+Trigger time: when the **\** is destroyed, in the same manner as that when an ArkUI component is destroyed. The figure below shows the time sequence of the **onDestroy** event and the **OnSurfaceDestroyed** event at the native layer.
+
+
+
+## How to Develop
+The following describes how to use the **\** to call the native APIs to create the EGL/GLES environment, draw graphics on the main page, and change graphics colors.
+
+1. Define the **\** on the GUI.
+
+ ```typescript
+ // ...
+ // Define XComponent in an .ets file.
+ XComponent({
+ id: 'xcomponentId',
+ type: XComponentType.SURFACE,
+ libraryname: 'nativerender'
+ })
+ .focusable(true) // Set the component to be able to respond to key events.
+ .onLoad((xComponentContext) => {
+ this.xComponentContext = xComponentContext;
+ })
+ .onDestroy(() => {
+ console.log("onDestroy");
+ })
+ // ...
+ ```
+
+2. Register the N-API module. For details, see [Using Native APIs in Application Projects](https://gitee.com/openharmony/docs/blob/master/en/application-dev/napi/napi-guidelines.md).
+
+ ```c++
+ // In the napi_init.cpp file, use the Init method to register the target function to transfer the encapsulated C++ methods for the JS side to call.
+ EXTERN_C_START
+ static napi_value Init(napi_env env, napi_value exports)
+ {
+ // ...
+ // Expose the getContext() API to the JS side.
+ napi_property_descriptor desc[] = {
+ { "getContext", nullptr, PluginManager::GetContext, nullptr, nullptr, nullptr, napi_default, nullptr }
+ };
+ if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed");
+ return nullptr;
+ }
+ // Check whether the environment variables in the method contain the instance. If the instance exists, register the drawing-related API.
+ PluginManager::GetInstance()->Export(env, exports);
+ return exports;
+ }
+ EXTERN_C_END
+
+ // Write the API description. You can modify the corresponding parameters as required.
+ static napi_module nativerenderModule = {
+ .nm_version = 1,
+ .nflag_s = 0,
+ .nm_filename = nullptr,
+ // Entry function
+ .nm_register_func = Init,
+ // Module name
+ .nm_modname = "nativerender",
+ .nm_priv = ((void *)0),
+ .reserved = { 0 }
+ };
+
+ // The method decorated by __attribute__((constructor)) is automatically called by the system. The N-API napi_module_register() is used to transfer the module description for module registration.
+ extern "C" __attribute__((constructor)) void RegisterModule(void)
+ {
+ napi_module_register(&nativerenderModule);
+ }
+
+ // Use the napi_define_properties method in the N-APIs to expose the drawPattern() method to the JS side and call the drawPattern() method on the JS side to draw content.
+ void PluginRender::Export(napi_env env, napi_value exports)
+ {
+ // ...
+ // Register the function as the JS API drawPattern.
+ napi_property_descriptor desc[] = {
+ { "drawPattern", nullptr, PluginRender::NapiDrawPattern, nullptr, nullptr, nullptr, napi_default, nullptr }
+ };
+ if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: napi_define_properties failed");
+ }
+ }
+ ```
+
+3. Register the **\** event callback and use the N-API to implement it.
+
+ (1) Define the callbacks for the touch event of the **\** and for when a surface is successfully created, changed, or destroyed.
+
+ ```c++
+ // Define the OnSurfaceCreatedCB() function to encapsulate the initialization environment and drawing background.
+ void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
+ {
+ // ...
+ // Obtain the ID of the , that is, the id parameter in the struct on the JS side.
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
+ "OnSurfaceCreatedCB: Unable to get XComponent id");
+ return;
+ }
+
+ // Initialize the environment and draw the background.
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ uint64_t width;
+ uint64_t height;
+ // Obtain the size of the surface held by the .
+ int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
+ if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) {
+ if (render->eglCore_->EglContextInit(window, width, height)) {
+ render->eglCore_->Background();
+ }
+ }
+ }
+
+ // Define the OnSurfaceChangedCB() function.
+ void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window)
+ {
+ // ...
+ // Obtain the ID of the .
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
+ "OnSurfaceChangedCB: Unable to get XComponent id");
+ return;
+ }
+
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ if (render != nullptr) {
+ // Encapsulate the OnSurfaceChanged method.
+ render->OnSurfaceChanged(component, window);
+ }
+ }
+
+ // Define the OnSurfaceDestroyedCB() function and encapsulate in it the Release() method in the PluginRender class for releasing resources.
+ void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
+ {
+ // ...
+ // Obtain the ID of the .
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
+ "OnSurfaceDestroyedCB: Unable to get XComponent id");
+ return;
+ }
+
+ std::string id(idStr);
+ // Release resources.
+ PluginRender::Release(id);
+ }
+
+ // Define the DispatchTouchEventCB() function, which is triggered when a touch event is responded to.
+ void DispatchTouchEventCB(OH_NativeXComponent *component, void *window)
+ {
+ // ...
+ // Obtain the ID of the .
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
+ "DispatchTouchEventCB: Unable to get XComponent id");
+ return;
+ }
+
+ std::string id(idStr);
+ PluginRender *render = PluginRender::GetInstance(id);
+ if (render != nullptr) {
+ // Encapsulate the OnTouchEvent method.
+ render->OnTouchEvent(component, window);
+ }
+ }
+
+ // Define the DispatchMouseEventCB() function, which is triggered when a mouse event is responded to.
+ void DispatchMouseEventCB(OH_NativeXComponent *component, void *window) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchMouseEventCB");
+ int32_t ret;
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
+ if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ return;
+ }
+
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ if (render) {
+ // Encapsulate the OnMouseEvent method.
+ render->OnMouseEvent(component, window);
+ }
+ }
+
+ // Define the DispatchHoverEventCB() function, which is triggered when the mouse pointer hover event is responded to.
+ void DispatchHoverEventCB(OH_NativeXComponent *component, bool isHover) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchHoverEventCB");
+ int32_t ret;
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
+ if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ return;
+ }
+
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ if (render) {
+ // Encapsulate the OnHoverEvent method.
+ render->OnHoverEvent(component, isHover);
+ }
+ }
+
+ // Define the OnFocusEventCB() function, which is triggered when a focus obtaining event is responded to.
+ void OnFocusEventCB(OH_NativeXComponent *component, void *window) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnFocusEventCB");
+ int32_t ret;
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
+ if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ return;
+ }
+
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ if (render) {
+ // Encapsulate the OnFocusEvent method.
+ render->OnFocusEvent(component, window);
+ }
+ }
+
+ // Define the OnBlurEventCB() function, which is triggered when the focus loss event is responded to.
+ void OnBlurEventCB(OH_NativeXComponent *component, void *window) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnBlurEventCB");
+ int32_t ret;
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
+ if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ return;
+ }
+
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ if (render) {
+ // Encapsulate the OnBlurEvent method.
+ render->OnBlurEvent(component, window);
+ }
+ }
+
+ // Define the OnKeyEventCB() function, which is triggered when a key event is responded to.
+ void OnKeyEventCB(OH_NativeXComponent *component, void *window) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnKeyEventCB");
+ int32_t ret;
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
+ if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ return;
+ }
+ std::string id(idStr);
+ auto render = PluginRender::GetInstance(id);
+ if (render) {
+ // Encapsulate the OnKeyEvent method.
+ render->OnKeyEvent(component, window);
+ }
+ }
+
+ // Define an OnSurfaceChanged() method.
+ void PluginRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window)
+ {
+ // ...
+ std::string id(idStr);
+ PluginRender* render = PluginRender::GetInstance(id);
+ double offsetX;
+ double offsetY;
+ // Obtain the offset of the surface held by the relative to the upper left corner of the window.
+ OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY);
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OH_NativeXComponent_GetXComponentOffset",
+ "offsetX = %{public}lf, offsetY = %{public}lf", offsetX, offsetY);
+ uint64_t width;
+ uint64_t height;
+ OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
+ if (render != nullptr) {
+ render->eglCore_->UpdateSize(width, height);
+ }
+ }
+
+ // Define an OnTouchEvent() method.
+ void PluginRender::OnTouchEvent(OH_NativeXComponent* component, void* window)
+ {
+ // ...
+ OH_NativeXComponent_TouchEvent touchEvent;
+ // Obtain the touch event triggered by the .
+ OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent);
+ std::string id(idStr);
+ PluginRender* render = PluginRender::GetInstance(id);
+ if (render != nullptr && touchEvent.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) {
+ render->eglCore_->ChangeColor();
+ hasChangeColor_ = 1;
+ }
+ float tiltX = 0.0f;
+ float tiltY = 0.0f;
+ OH_NativeXComponent_TouchPointToolType toolType =
+ OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN;
+ // Obtain the tool type of the touch point.
+ OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType);
+ // Obtain the tilt angle of the touch point relative to the x-axis.
+ OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX);
+ // Obtain the tilt angle of the touch point relative to the y-axis.
+ OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY);
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent",
+ "touch info: toolType = %{public}d, tiltX = %{public}lf, tiltY = %{public}lf", toolType, tiltX, tiltY);
+ }
+
+ // Define an OnMouseEvent() method.
+ void PluginRender::OnMouseEvent(OH_NativeXComponent *component, void *window) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnMouseEvent");
+ OH_NativeXComponent_MouseEvent mouseEvent;
+ // Obtain the mouse event triggered by the .
+ int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent);
+ if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "MouseEvent Info: x = %{public}f, y = %{public}f, action = %{public}d, button = %{public}d", mouseEvent.x, mouseEvent.y, mouseEvent.action, mouseEvent.button);
+ } else {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetMouseEvent error");
+ }
+ }
+
+ // Define an OnMouseEvent() method.
+ void PluginRender::OnKeyEvent(OH_NativeXComponent *component, void *window) {
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnKeyEvent");
+
+ OH_NativeXComponent_KeyEvent *keyEvent = nullptr;
+ // Obtain the key event triggered by the .
+ if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) {
+ OH_NativeXComponent_KeyAction action;
+ // Obtain the action of a key event.
+ OH_NativeXComponent_GetKeyEventAction(keyEvent, &action);
+ OH_NativeXComponent_KeyCode code;
+ // Obtain the key code value of a key event.
+ OH_NativeXComponent_GetKeyEventCode(keyEvent, &code);
+ OH_NativeXComponent_EventSourceType sourceType;
+ // Obtain the input source type of a key event.
+ OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType);
+ int64_t deviceId;
+ // Obtain the device ID of a key event.
+ OH_NativeXComponent_GetKeyEventDeviceId(keyEvent, &deviceId);
+ int64_t timeStamp;
+ // Obtain the timestamp of a key event.
+ OH_NativeXComponent_GetKeyEventTimestamp(keyEvent, &timeStamp);
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "KeyEvent Info: action=%{public}d, code=%{public}d, sourceType=%{public}d, deviceId=%{public}ld, timeStamp=%{public}ld", action, code, sourceType, deviceId, timeStamp);
+ } else {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetKeyEvent error");
+ }
+ }
+ ```
+
+ (2) Register the **\** event callback and call the method defined in step 3.1 when the **\** event is triggered.
+
+ ```c++
+ void PluginRender::RegisterCallback(OH_NativeXComponent *nativeXComponent) {
+ // Set the callback of the component creation event. When the component is created, related operations are triggered to initialize the environment and draw the background.
+ renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB;
+ // Set the callback of the component change event. When the component changes, related operations are triggered.
+ renderCallback_.OnSurfaceChanged = OnSurfaceChangedCB;
+ // Set the callback of the component destruction event. When the component is destroyed, related operations are triggered to release the requested resources.
+ renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
+ // Set the callback of the touch event. When the touch event is triggered, the N-API is called to call the original C++ method.
+ renderCallback_.DispatchTouchEvent = DispatchTouchEventCB;
+ // Register OH_NativeXComponent_Callback with NativeXComponent.
+ OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_);
+
+ // Set the callback of the mouse event. When the event is triggered, the N-API is called to call the original C++ method.
+ mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB;
+ // Set the callback of the mouse event. When the event is triggered, the N-API is called to call the original C++ method.
+ mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB;
+ // Register OH_NativeXComponent_MouseEvent_Callback with NativeXComponent.
+ OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback_);
+
+ // Register the OnFocusEventCB method with NativeXComponent.
+ OH_NativeXComponent_RegisterFocusEventCallback(nativeXComponent, OnFocusEventCB);
+ // Register the OnKeyEventCB method with NativeXComponent.
+ OH_NativeXComponent_RegisterKeyEventCallback(nativeXComponent, OnKeyEventCB);
+ // Register the OnBlurEventCB method with NativeXComponent.
+ OH_NativeXComponent_RegisterBlurEventCallback(nativeXComponent, OnBlurEventCB);
+ }
+ ```
+
+ (3) Define the **NapiDrawPattern** method, which will be called by the **drawPattern()** method exposed to the JS side.
+
+ ```c++
+ napi_value PluginRender::NapiDrawPattern(napi_env env, napi_callback_info info)
+ {
+ // ...
+ // Obtain environment variables.
+ napi_value thisArg;
+ if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_get_cb_info fail");
+ return nullptr;
+ }
+
+ // Obtain the XComponent instance from the environment variables.
+ napi_value exportInstance;
+ if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender",
+ "NapiDrawPattern: napi_get_named_property fail");
+ return nullptr;
+ }
+
+ // Use napi_unwrap to obtain the pointer to the XComponent instance.
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_unwrap fail");
+ return nullptr;
+ }
+
+ // Obtain the ID of the XComponent instance.
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender",
+ "NapiDrawPattern: Unable to get XComponent id");
+ return nullptr;
+ }
+
+ std::string id(idStr);
+ PluginRender *render = PluginRender::GetInstance(id);
+ if (render) {
+ // Call the drawing method.
+ render->eglCore_->Draw();
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->eglCore_->Draw() executed");
+ }
+ return nullptr;
+ }
+ ```
+
+4. Initialize the environment, including initializing the available EGLDisplay, determining the available surface configuration, creating the rendering area surface, and creating and associating the context.
+
+ ```c++
+ void EGLCore::UpdateSize(int width, int height)
+ {
+ width_ = width;
+ height_ = height;
+ if (width_ > 0) {
+ // Calculate the width percentage of the drawn rectangle.
+ width_Percent_ = FIFTY_PERCENT * height_ / width_;
+ }
+ }
+
+ bool EGLCore::EglContextInit(void *window, int width, int height)
+ {
+ // ...
+ UpdateSize(width, height);
+ eglWindow_ = static_cast(window);
+
+ // Initialize the display.
+ eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay_ == EGL_NO_DISPLAY) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display");
+ return false;
+ }
+
+ // Initialize the EGL.
+ EGLint majorVersion;
+ EGLint minorVersion;
+ if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore",
+ "eglInitialize: unable to get initialize EGL display");
+ return false;
+ }
+
+ // Select the configuration.
+ const EGLint maxConfigSize = 1;
+ EGLint numConfigs;
+ if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs");
+ return false;
+ }
+
+ // Create an environment.
+ return CreateEnvironment();
+ }
+ ```
+
+ ```c++
+ bool EGLCore::CreateEnvironment()
+ {
+ // ...
+ // Create a surface.
+ eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL);
+
+ // ...
+ // Create a context.
+ eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
+ if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed");
+ return false;
+ }
+
+ // Create a program.
+ program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER);
+ if (program_ == PROGRAM_ERROR) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program");
+ return false;
+ }
+ return true;
+ }
+ ```
+
+5. Implement the rendering function.
+
+ (1) Draw the background.
+
+ ```c++
+ // Draw the background color #f4f4f4.
+ const GLfloat BACKGROUND_COLOR[] = { 244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f };
+
+ // Draw the background vertex.
+ const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {
+ -1.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, -1.0f,
+ -1.0f, -1.0f
+ };
+ ```
+
+ ```c++
+ // Draw the background color.
+ void EGLCore::Background()
+ {
+ GLint position = PrepareDraw();
+ if (position == POSITION_ERROR) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed");
+ return;
+ }
+
+ if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES,
+ sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed");
+ return;
+ }
+
+ if (!FinishDraw()) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed");
+ return;
+ }
+ }
+
+ // Prepare for drawing and obtain the value of position. When the creation is successful, the value of position starts from 0.
+ GLint EGLCore::PrepareDraw()
+ {
+ if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) ||
+ (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error");
+ return POSITION_ERROR;
+ }
+
+ glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_);
+ glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(program_);
+
+ return glGetAttribLocation(program_, POSITION_NAME);
+ }
+
+ // Draw a specified color in the specified area based on the input parameters.
+ bool EGLCore::ExecuteDraw(GLint position, const GLfloat *color, const GLfloat shapeVertices[],
+ unsigned long vertSize)
+ {
+ if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0]) != SHAPE_VERTICES_SIZE)) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
+ return false;
+ }
+
+ glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
+ glEnableVertexAttribArray(position);
+ glVertexAttrib4fv(1, color);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
+ glDisableVertexAttribArray(position);
+
+ return true;
+ }
+
+ // End the drawing operation.
+ bool EGLCore::FinishDraw()
+ {
+ // Forcibly refresh the buffer.
+ glFlush();
+ glFinish();
+ return eglSwapBuffers(eglDisplay_, eglSurface_);
+ }
+ ```
+
+ (2) Draw the shape.
+
+ ```c++
+ void EGLCore::Draw()
+ {
+ flag_ = false;
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw");
+ GLint position = PrepareDraw();
+ if (position == POSITION_ERROR) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed");
+ return;
+ }
+
+ // Draw the background.
+ if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES,
+ sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed");
+ return;
+ }
+
+ // Divide the pentagon into five quadrilaterals and calculate the four vertices of one of the quadrilaterals.
+ GLfloat rotateX = 0;
+ GLfloat rotateY = FIFTY_PERCENT * height_;
+ GLfloat centerX = 0;
+ GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
+ GLfloat leftX = -rotateY * (M_PI / 180 * 18);
+ GLfloat leftY = 0;
+ GLfloat rightX = rotateY * (M_PI / 180 * 18);
+ GLfloat rightY = 0;
+
+ // Determine the vertices for drawing the quadrilateral, which are represented by the percentage of the drawing area.
+ const GLfloat shapeVertices[] = {
+ centerX / width_, centerY / height_,
+ leftX / width_, leftY / height_,
+ rotateX / width_, rotateY / height_,
+ rightX / width_, rightY / height_
+ };
+
+ if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed");
+ return;
+ }
+
+ GLfloat rad = M_PI / 180 * 72;
+ for (int i = 0; i < 4; ++i)
+ {
+ // Obtain the vertices of the other four quadrilaterals through rotation.
+ rotate2d(centerX, centerY, &rotateX, &rotateY,rad);
+ rotate2d(centerX, centerY, &leftX, &leftY,rad);
+ rotate2d(centerX, centerY, &rightX, &rightY,rad);
+
+ // Determine the vertices for drawing the quadrilateral, which are represented by the percentage of the drawing area.
+ const GLfloat shapeVertices[] = {
+ centerX / width_, centerY / height_,
+ leftX / width_, leftY / height_,
+ rotateX / width_, rotateY / height_,
+ rightX / width_, rightY / height_
+ };
+
+ // Draw the shape.
+ if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed");
+ return;
+ }
+ }
+
+ // End drawing.
+ if (!FinishDraw()) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed");
+ return;
+ }
+
+ flag_ = true;
+ }
+ ```
+
+ (3) Change the colors, by drawing a new shape with the same size but different colors and replacing the original shape with the new shape.
+
+ ```c++
+ void EGLCore::ChangeColor()
+ {
+ if (!flag_) {
+ return;
+ }
+ OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor");
+ GLint position = PrepareDraw();
+ if (position == POSITION_ERROR) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed");
+ return;
+ }
+
+ // Draw the background.
+ if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES,
+ sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed");
+ return;
+ }
+
+ // Determine the vertices for drawing the quadrilateral, which are represented by the percentage of the drawing area.
+ GLfloat rotateX = 0;
+ GLfloat rotateY = FIFTY_PERCENT * height_;
+ GLfloat centerX = 0;
+ GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
+ GLfloat leftX = -rotateY * (M_PI / 180 * 18);
+ GLfloat leftY = 0;
+ GLfloat rightX = rotateY * (M_PI / 180 * 18);
+ GLfloat rightY = 0;
+
+ // Determine the vertices for drawing the quadrilateral, which are represented by the percentage of the drawing area.
+ const GLfloat shapeVertices[] = {
+ centerX / width_, centerY / height_,
+ leftX / width_, leftY / height_,
+ rotateX / width_, rotateY / height_,
+ rightX / width_, rightY / height_
+ };
+
+ // Use the new colors for drawing.
+ if (!ExecuteDrawStar2(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed");
+ return;
+ }
+
+ GLfloat rad = M_PI / 180 * 72;
+ for (int i = 0; i < 4; ++i)
+ {
+ // Obtain the vertices of the other four quadrilaterals through rotation.
+ rotate2d(centerX, centerY, &rotateX, &rotateY,rad);
+ rotate2d(centerX, centerY, &leftX, &leftY,rad);
+ rotate2d(centerX, centerY, &rightX, &rightY,rad);
+
+ // Determine the vertices for drawing the quadrilateral, which are represented by the percentage of the drawing area.
+ const GLfloat shapeVertices[] = {
+ centerX / width_, centerY / height_,
+ leftX / width_, leftY / height_,
+ rotateX / width_, rotateY / height_,
+ rightX / width_, rightY / height_
+ };
+
+ // Use the new colors for drawing.
+ if (!ExecuteDrawStar2(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw star failed");
+ return;
+ }
+ }
+
+ // End drawing.
+ if (!FinishDraw()) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed");
+ }
+ }
+ ```
+
+6. Release related resources.
+
+ (1) Create the **Release()** method in the **EGLCore** class to release the resources requested during environment initialization, including the window display, rendering area surface, and environment context.
+
+ ```c++
+ void EGLCore::Release()
+ {
+ // Release the surface.
+ if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed");
+ }
+ // Release the context.
+ if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed");
+ }
+ // Release the display.
+ if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) {
+ OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed");
+ }
+ }
+ ```
+
+ (2) Add the **Release()** method to the **PluginRender** class to release the **EGLCore** and **PluginRender** instances.
+
+ ```c++
+ void PluginRender::Release(std::string &id)
+ {
+ PluginRender *render = PluginRender::GetInstance(id);
+ if (render != nullptr) {
+ render->eglCore_->Release();
+ delete render->eglCore_;
+ render->eglCore_ = nullptr;
+ delete render;
+ render = nullptr;
+ instance_.erase(instance_.find(id));
+ }
+ }
+ ```
+
+7. Use the CMake toolchain to compile the C++ source code into a dynamic link library (DLL) file.
+
+ ```CMake
+ # Set the minimum CMake version.
+ cmake_minimum_required(VERSION 3.4.1)
+ # Project name
+ project(XComponent)
+
+ set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+ add_definitions(-DOHOS_PLATFORM)
+ # Set the header file search directory.
+ include_directories(
+ ${NATIVERENDER_ROOT_PATH}
+ ${NATIVERENDER_ROOT_PATH}/include
+ )
+ # Add the **nativerender** dynamic library, with the **libnativerender.so** library file. Add the .cpp file.
+ add_library(nativerender SHARED
+ render/egl_core.cpp
+ render/plugin_render.cpp
+ manager/plugin_manager.cpp
+ napi_init.cpp
+ )
+
+ find_library(
+ EGL-lib
+ EGL
+ )
+
+ find_library(
+ GLES-lib
+ GLESv3
+ )
+
+ find_library(
+ hilog-lib
+ hilog_ndk.z
+ )
+
+ find_library(
+ libace-lib
+ ace_ndk.z
+ )
+
+ find_library(
+ libnapi-lib
+ ace_napi.z
+ )
+
+ find_library(
+ libuv-lib
+ uv
+ )
+ # Add the library to be linked.
+ target_link_libraries(nativerender PUBLIC
+ ${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib})
+ ```
+
+##
+
+
+
+-
diff --git a/en/application-dev/performance/Readme.md b/en/application-dev/performance/Readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..8172a210af94348fdb22831295c90a19b74965e6
--- /dev/null
+++ b/en/application-dev/performance/Readme.md
@@ -0,0 +1,33 @@
+# Best Practices for Application Performance
+
+This topic outlines some best practices for improving your application performance to live up to user expectations for quick startup, timely response, and no frame freezing.
+
+Following these practices, you can reduce your application's startup time, response time, and frame loss.
+
+- Improving application startup and response time
+
+ - [Speeding Up Application Cold Start](../performance/improve-application-startup-and-response/improve-application-cold-start-speed.md)
+
+ Application startup latency is a key factor that affects user experience. To speed up the application cold start, you are advised to perform optimization in the following four phases:
+
+ 1. Application process creation and initialization
+
+ 2. Application and ability initialization
+
+ 3. Ability lifecycle
+
+ 4. Home page loading and drawing
+
+ - [Speeding Up Application Response](../performance/improve-application-startup-and-response/improve-application-response.md)
+
+ A premium interaction experience requires quick response to user input. To improve your application's response time, you are advised to prevent the main thread from being blocked by non-UI tasks and reduce the number of component to be refreshed.
+
+- Reducing frame loss
+
+ - [Reducing Nesting](../performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md)
+
+ The smoothness of rendering the layout to the screen affects the user perceived quality. It is recommended that you minimize nesting in your code to shorten the render time.
+
+ - [Reducing Frame Loss](../performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md)
+
+ Whether animations in your application run smoothly is a key factor that affects user experience. You are advised to use the system-provided animation APIs to reduce frame loss.
diff --git a/en/application-dev/performance/figure/application-cold-start.png b/en/application-dev/performance/figure/application-cold-start.png
new file mode 100644
index 0000000000000000000000000000000000000000..210664879280518713b3ccb309875a059523319c
Binary files /dev/null and b/en/application-dev/performance/figure/application-cold-start.png differ
diff --git a/en/application-dev/performance/improve-application-startup-and-response/improve-application-cold-start-speed.md b/en/application-dev/performance/improve-application-startup-and-response/improve-application-cold-start-speed.md
new file mode 100644
index 0000000000000000000000000000000000000000..b99c5dfc0ac84d75954b53b3a5c291bf60f4314e
--- /dev/null
+++ b/en/application-dev/performance/improve-application-startup-and-response/improve-application-cold-start-speed.md
@@ -0,0 +1,110 @@
+# Speeding Up Application Cold Start
+
+Application startup latency is a key factor that affects user experience. When an application is started, the background does not have a process of the application, and therefore the system creates a new process and allocates it to the application. This startup mode is called cold start.
+
+## Analyzing the Time Required for Application Cold Start
+
+The cold start process of OpenHarmony applications can be divided into four phases: application process creation and initialization, application and ability initialization, ability lifecycle, and home page loading and drawing, as shown in the following figure.
+
+
+
+## 1. Shortening Time Required for Application Process Creation And Initialization
+
+In the phase of application process creation and initialization, the system creates and initializes an application process, including decoding the icon of the startup page (specified by **startWindowIcon**).
+
+### Using startWindowIcon of Appropriate Resolution
+
+With regard to the icon of the startup page, the recommended maximum resolution is 256 x 256 pixels. Larger resolutions may result in slow startup.
+
+```json
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntrance": "./ets/entryability/EntryAbility.ts",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startWindowIcon", // Modify the icon of the startup page. It is recommended that the icon be less than or equal to 256 pixels x 256 pixels.
+ "startWindowBackground": "$color:start_window_background",
+ "visible": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+```
+
+## 2. Shortening Time Required for Application and Ability Initialization
+
+In this phase of application and ability initialization, resources are loaded, VMs are created, application and ability related objects are created and initialized, and dependent modules are loaded.
+
+### Minimizing the Number of Imported Modules
+
+Before the application code is executed, the application must find and load all imported modules. Each additional third-party framework or module to be loaded by the application increases the startup time. The time required depends on the number and size of loaded third-party frameworks or modules. To speed up startup, use system-provided modules when possible and load the modules as required.
+
+## 3. Shortening Time Required for Ability Lifecycle
+
+In this phase of ability lifecycle, the ability lifecycle callbacks are executed.
+
+### Avoiding Time-Consuming Operations in Ability Lifecycle Callbacks
+
+In the application startup process, the system executes the ability lifecycle callbacks. Whenever possible, avoid performing time-consuming operations in these callbacks. You are advised to perform time-consuming operations through asynchronous tasks or execute them in other threads.
+
+In these lifecycle callbacks, perform only necessary operations. For details, see [UIAbility Lifecycle](https://gitee.com/openharmony/docs/blob/master/en/application-dev/application-models/uiability-lifecycle.md).
+
+## 4. Shortening Time Required for Home Page Loading and Drawing
+
+In this phase of home page loading and drawing, the home page content is loaded, the layout is measured, and components are refreshed and drawn.
+
+### Avoid time-consuming operations in the custom component lifecycle callbacks.
+
+When the lifecycle of a custom component changes, the corresponding callback is called.
+
+The **aboutToAppear** function is executed after the custom component instance is created and before the page is drawn. The following code asynchronously processes the time-consuming computing task in **aboutToAppear** to avoid executing the operation in this function and blocking the page drawing.
+
+```javascript
+@Entry
+@Component
+struct Index {
+ @State private text: string = undefined;
+ private count: number = undefined;
+
+ aboutToAppear() {
+ this.computeTaskAsync(); // Asynchronous task
+ this.text = "hello world";
+ }
+
+ build() {
+ Column({space: 10}) {
+ Text(this.text).fontSize(50)
+ }
+ .width('100%')
+ .height('100%')
+ .padding(10)
+ }
+
+ computeTask() {
+ this.count = 0;
+ while (this.count < 10000000) {
+ this.count++;
+ }
+ this.text = 'task complete';
+ }
+
+ // Asynchronous processing of the computing task
+ private computeTaskAsync() {
+ new Promise((resolved, rejected) => {
+ setTimeout(() => {// setTimeout is used to implement asynchronous processing.
+ this.computeTask();
+ }, 1000)
+ })
+ }
+}
+```
diff --git a/en/application-dev/performance/improve-application-startup-and-response/improve-application-response.md b/en/application-dev/performance/improve-application-startup-and-response/improve-application-response.md
new file mode 100644
index 0000000000000000000000000000000000000000..b740edb6f1f4e2df007631f6feef966762e0d2ba
--- /dev/null
+++ b/en/application-dev/performance/improve-application-startup-and-response/improve-application-response.md
@@ -0,0 +1,325 @@
+# Speeding Up Application Response
+
+This topic provides the following tips for improving your application's response to user input.
+
+- Prevent the main thread from being blocked by non-UI tasks.
+- Reduce the number of components to be refreshed.
+
+## Preventing Main Thread from Being Blocked by Non-UI Tasks
+
+When the application responds to user input, its main thread should execute only UI tasks (such as preparation of data to be displayed and update of visible components). It is recommended that non-UI, time-consuming tasks (such as long-time content loading) be executed through asynchronous tasks or allocated to other threads.
+
+### Using Asynchronous Component Loading
+
+The **\** component has the asynchronous loading feature enabled by default. When an application loads a batch of local images to be displayed on the page, blank placeholder icons are displayed first, and then replaced by the images when these images have finished loading in other threads. In this way, image loading does not block page display. The following code is recommended only when the image loading takes a short time.
+
+```javascript
+@Entry
+@Component
+struct ImageExample1 {
+ build() {
+ Column() {
+ Row() {
+ Image('resources/base/media/sss001.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%')
+ Image('resources/base/media/sss002.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%')
+ Image('resources/base/media/sss003.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%')
+ Image('resources/base/media/sss004.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%')
+ }
+ // Several containers are omitted here. Each container contains the preceding components.
+ }
+ }
+}
+```
+
+Recommendation: If it takes a short time to load an image, the benefits of asynchronous loading will be greatly undermined. In this case, change the value of the syncLoad attribute.
+
+```javascript
+@Entry
+@Component
+struct ImageExample1 {
+ build() {
+ Column() {
+ Row() {
+ Image('resources/base/media/sss001.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%').syncLoad(true)
+ Image('resources/base/media/sss002.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%').syncLoad(true)
+ Image('resources/base/media/sss003.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%').syncLoad(true)
+ Image('resources/base/media/sss004.jpg')
+ .border({ width: 1 }).borderStyle(BorderStyle.Dashed).aspectRatio(1).width('25%').height('12.5%').syncLoad(true)
+ }
+ // Several containers are omitted here. Each container contains the preceding components.
+ }
+ }
+}
+```
+
+### Using TaskPool for Asynchronous Processing
+
+Compared with the worker thread, [TaskPool](https://gitee.com/sqsyqqy/docs/blob/master/en/application-dev/reference/apis/js-apis-taskpool.md) provides the task priority setting and automatic thread pool management mechanism. The following is an example:
+
+```javascript
+import taskpool from '@ohos.taskpool';
+
+@Concurrent
+function computeTask(arr: string[]): string[] {
+ // Simulate a compute-intensive task.
+ let count = 0;
+ while (count < 100000000) {
+ count++;
+ }
+ return arr.reverse();
+}
+
+@Entry
+@Component
+struct AspectRatioExample {
+ @State children: string[] = ['1', '2', '3', '4', '5', '6'];
+
+ aboutToAppear() {
+ this.computeTaskInTaskPool();
+ }
+
+ async computeTaskInTaskPool() {
+ const param = this.children.slice();
+ let task = new taskpool.Task(computeTask, param);
+ // @ts-ignore
+ this.children = await taskpool.execute(task);
+ }
+
+ build() {
+ // Component layout
+ }
+}
+```
+
+### Creating Asynchronous Tasks
+
+The following code shows how to declare a long-running non-UI task as an asynchronous task through **Promise**. This allows the main thread to first focus on providing user feedback and completing the initial render, and then execute the asynchronous task when it is idle. After the asynchronous task is complete, related components are redrawn to refresh the page.
+
+```javascript
+@Entry
+@Component
+struct AspectRatioExample {
+ @State private children: string[] = ['1', '2', '3', '4', '5', '6'];
+ private count: number = undefined;
+
+ aboutToAppear() {
+ this.computeTaskAsync(); // Invoke the asynchronous compute function.
+ }
+
+ // Simulate a compute-intensive task.
+ computeTask() {
+ this.count = 0;
+ while (this.count < 100000000) {
+ this.count++;
+ }
+ this.children = this.children.reverse();
+ }
+
+ computeTaskAsync() {
+ new Promise((resolved, rejected) => {
+ setTimeout(() => {// setTimeout is used to implement asynchronous processing.
+ this.computeTask();
+ }, 1000)
+ })
+ }
+
+ build() {
+ // Component layout
+ }
+}
+```
+
+## Reducing the Number of Components to Be Refreshed
+
+When an application refreshes a page, the number of components to be refreshed must be reduced as much as possible. If this number is too large, the main thread will take a long time to perform measurement and layout. In addition, the **aboutToAppear()** and **aboutToDisappear()** APIs will be called multiple times during the creation and destruction of custom components, increasing the load of the main thread.
+
+### Limiting the Refresh Scope with Containers
+
+Negative example: If a component in a container is included in the **if** condition, changes in the **if** condition result will trigger the creation and destruction of the component. If the container layout is affected in this case, all components in the container are refreshed. As a result, the UI refresh of the main thread takes a long time.
+
+In the following example, the **Text('New Page')** component is controlled by the state variable **isVisible**. When **isVisible** is set to **true**, the component is created. When **isVisible** is set to **false**, the component is destroyed. This means that, when the value of **isVisible** changes, all components in the **\** container are refreshed.
+
+```javascript
+@Entry
+@Component
+struct StackExample {
+ @State isVisible : boolean = false;
+
+ build() {
+ Column() {
+ Stack({alignContent: Alignment.Top}) {
+ Text().width('100%').height('70%').backgroundColor(0xd2cab3)
+ .align(Alignment.Center).textAlign(TextAlign.Center);
+
+ // 100 identical components are omitted here.
+
+ if (this.isVisible) {
+ Text('New Page').height("100%").height("70%").backgroundColor(0xd2cab3)
+ .align(Alignment.Center).textAlign(TextAlign.Center);
+ }
+ }
+ Button("press").onClick(() => {
+ this.isVisible = !(this.isVisible);
+ })
+ }
+ }
+}
+```
+
+Recommendation: For the component controlled by the state variable, add a container to the **if** statement to reduce the refresh scope.
+
+```javascript
+@Entry
+@Component
+struct StackExample {
+ @State isVisible : boolean = false;
+
+ build() {
+ Column() {
+ Stack({alignContent: Alignment.Top}) {
+ Text().width('100%').height('70%').backgroundColor(0xd2cab3)
+ .align(Alignment.Center).textAlign(TextAlign.Center);
+
+ // 100 identical components are omitted here.
+
+ Stack() {
+ if (this.isVisible) {
+ Text('New Page').height("100%").height("70%").backgroundColor(0xd2cab3)
+ .align(Alignment.Center).textAlign(TextAlign.Center);
+ }
+ }.width('100%').height('70%')
+ }
+ Button("press").onClick(() => {
+ this.isVisible = !(this.isVisible);
+ })
+ }
+ }
+}
+```
+
+### Implementing On-Demand Loading of List Items
+
+Negative example: Each of the 10000 elements in **this.arr** is initialized and loaded. As a result, the execution of the main thread takes a long time.
+
+```javascript
+@Entry
+@Component
+struct MyComponent {
+ @State arr: number[] = Array.from(Array(10000), (v,k) =>k);
+ build() {
+ List() {
+ ForEach(this.arr, (item: number) => {
+ ListItem() {
+ Text(`item value: ${item}`)
+ }
+ }, (item: number) => item.toString())
+ }
+ }
+}
+```
+
+Recommendation: In similar cases, replace **ForEach** with **LazyForEach** so that only visible elements are loaded.
+
+```javascript
+class BasicDataSource implements IDataSource {
+ private listeners: DataChangeListener[] = []
+
+ public totalCount(): number {
+ return 0
+ }
+
+ public getData(index: number): any {
+ return undefined
+ }
+
+ registerDataChangeListener(listener: DataChangeListener): void {
+ if (this.listeners.indexOf(listener) < 0) {
+ console.info('add listener')
+ this.listeners.push(listener)
+ }
+ }
+
+ unregisterDataChangeListener(listener: DataChangeListener): void {
+ const pos = this.listeners.indexOf(listener);
+ if (pos >= 0) {
+ console.info('remove listener')
+ this.listeners.splice(pos, 1)
+ }
+ }
+
+ notifyDataReload(): void {
+ this.listeners.forEach(listener => {
+ listener.onDataReloaded()
+ })
+ }
+
+ notifyDataAdd(index: number): void {
+ this.listeners.forEach(listener => {
+ listener.onDataAdd(index)
+ })
+ }
+
+ notifyDataChange(index: number): void {
+ this.listeners.forEach(listener => {
+ listener.onDataChange(index)
+ })
+ }
+
+ notifyDataDelete(index: number): void {
+ this.listeners.forEach(listener => {
+ listener.onDataDelete(index)
+ })
+ }
+
+ notifyDataMove(from: number, to: number): void {
+ this.listeners.forEach(listener => {
+ listener.onDataMove(from, to)
+ })
+ }
+}
+
+class MyDataSource extends BasicDataSource {
+ private dataArray: string[] = Array.from(Array(10000), (v, k) => k.toString());
+
+ public totalCount(): number {
+ return this.dataArray.length
+ }
+
+ public getData(index: number): any {
+ return this.dataArray[index]
+ }
+
+ public addData(index: number, data: string): void {
+ this.dataArray.splice(index, 0, data)
+ this.notifyDataAdd(index)
+ }
+
+ public pushData(data: string): void {
+ this.dataArray.push(data)
+ this.notifyDataAdd(this.dataArray.length - 1)
+ }
+}
+
+@Entry
+@Component
+struct MyComponent {
+ private data: MyDataSource = new MyDataSource()
+
+ build() {
+ List() {
+ LazyForEach(this.data, (item: string) => {
+ ListItem() {
+ Text(item).fontSize(20).margin({ left: 10 })
+ }
+ }, item => item)
+ }
+ }
+}
+```
diff --git a/en/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md b/en/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md
new file mode 100644
index 0000000000000000000000000000000000000000..a61c8649e392b7fd0055e63ab48e0fa335faab7f
--- /dev/null
+++ b/en/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md
@@ -0,0 +1,142 @@
+# Reducing Frame Loss
+
+Frame loss in the animation arena is a phenomenon where the frame rate of an animation drops when it is running or being created.
+
+When playing an animation, the system needs to calculate the animation curve and draw the component layout within a refresh period. You are advised to use the system-provided animation APIs. With these APIs, setting the curve type, end point position, and duration is enough for meeting common animation needs, thereby reducing the load of the UI main thread.
+
+Negative example: The application uses a custom animation, which involves animation curve calculation. This calculation process may cause high load of the UI thread and frame loss.
+
+```javascript
+@Entry
+@Component
+struct AttrAnimationExample {
+ @State widthSize: number = 200
+ @State heightSize: number = 100
+ @State flag: boolean = true
+
+ computeSize() {
+ let duration = 2000
+ let period = 16
+ let widthSizeEnd = undefined
+ let heightSizeEnd = undefined
+ if (this.flag) {
+ widthSizeEnd = 100
+ heightSizeEnd = 50
+ } else {
+ widthSizeEnd = 200
+ heightSizeEnd = 100
+ }
+ let doTimes = duration / period
+ let deltaHeight = (heightSizeEnd - this.heightSize) / doTimes
+ let deltaWeight = (widthSizeEnd - this.widthSize) / doTimes
+ for (let i = 1; i <= doTimes; i++) {
+ let t = period * (i);
+ setTimeout(() => {
+ this.heightSize = this.heightSize + deltaHeight
+ this.widthSize = this.widthSize + deltaWeight
+ }, t)
+ }
+ this.flag = !this.flag
+ }
+
+ build() {
+ Column() {
+ Button('click me')
+ .onClick(() => {
+ let delay = 500
+ setTimeout(() => { this.computeSize() }, delay)
+ })
+ .width(this.widthSize).height(this.heightSize).backgroundColor(0x317aff)
+ }.width('100%').margin({ top: 5 })
+ }
+}
+```
+
+## Using System-Provided Attribute Animation APIs
+
+The following uses the system-provided attribute animation APIs to implement the preceding animation features:
+
+```javascript
+@Entry
+@Component
+struct AttrAnimationExample {
+ @State widthSize: number = 200
+ @State heightSize: number = 100
+ @State flag: boolean = true
+
+ build() {
+ Column() {
+ Button('click me')
+ .onClick((event: ClickEvent) => {
+ if (this.flag) {
+ this.widthSize = 100
+ this.heightSize = 50
+ } else {
+ this.widthSize = 200
+ this.heightSize = 100
+ }
+ this.flag = !this.flag
+ })
+ .width(this.widthSize).height(this.heightSize).backgroundColor(0x317aff)
+ .animation({
+ duration: 2000, // Animation duration.
+ curve: Curve.Linear, // Animation curve.
+ delay: 500, // Animation delay.
+ iterations: 1, // Number of playback times.
+ playMode: PlayMode.Normal // Animation playback mode.
+ }) // Animation configuration for the width and height attributes of the component.
+ }.width('100%').margin({ top: 5 })
+ }
+}
+```
+
+For more details, see [Property Animator](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/arkui-ts/ts-animatorproperty.md).
+
+## Using System-Provided Explicit Animation APIs
+
+The following uses the system-provided explicit animation APIs to implement the preceding animation features:
+
+```javascript
+@Entry
+@Component
+struct AnimateToExample {
+ @State widthSize: number = 200;
+ @State heightSize: number = 100;
+ @State flag: boolean = true;
+
+ build() {
+ Column() {
+ Button('click me')
+ .onClick((event: ClickEvent) => {
+ if (this.flag) {
+ animateTo({
+ duration: 2000, // Animation duration.
+ curve: Curve.Linear, // Animation curve.
+ delay: 500, // Animation delay.
+ iterations: 1, // Number of playback times.
+ playMode: PlayMode.Normal // Animation playback mode.
+ }, () => {
+ this.widthSize = 100;
+ this.heightSize = 50;
+ })
+ } else {
+ animateTo({
+ duration: 2000, // Animation duration.
+ curve: Curve.Linear, // Animation curve.
+ delay: 500, // Animation delay.
+ iterations: 1, // Number of playback times.
+ playMode: PlayMode.Normal // Animation playback mode.
+ }, () => {
+ this.widthSize = 200;
+ this.heightSize = 100;
+ })
+ }
+ this.flag = !this.flag;
+ })
+ .width(this.widthSize).height(this.heightSize).backgroundColor(0x317aff)
+ }.width('100%').margin({ top: 5 })
+ }
+}
+```
+
+For more details, see [Explicit Animation](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/arkui-ts/ts-explicit-animation.md).
diff --git a/en/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md b/en/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md
new file mode 100644
index 0000000000000000000000000000000000000000..3d49aeff965aae8a5ea38a7728a2314eab2abdba
--- /dev/null
+++ b/en/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md
@@ -0,0 +1,64 @@
+# Reducing Nesting
+
+The view hierarchy can significantly affect application performance. For example, at the 120 Hz refresh rate, a device screen refreshes frames every 8.3 ms. If there are many levels of nested views, the frames may fail to be refreshed within 8.3 ms. As a result, frame loss and frame freezing occur, detracting from user experience. Therefore, it is recommended that you minimize nesting in your code to shorten the refresh time.
+
+## Removing Redundant Levels of Nesting
+
+In the following negative example, the **\** component is used to implement a grid, but it is nested inside three levels of **\** containers. As a result, the refresh and rendering process takes a long time to complete.
+
+```javascript
+@Entry
+@Component
+struct AspectRatioExample {
+ @State children: Number[] = Array.from(Array(900), (v, k) => k);
+
+ build() {
+ Scroll() {
+ Grid() {
+ ForEach(this.children, (item) => {
+ GridItem() {
+ Stack() {
+ Stack() {
+ Stack() {
+ Text(item.toString())
+ }
+ }
+ }
+ }
+ }, item => item)
+ }
+ .columnsTemplate('1fr 1fr 1fr 1fr')
+ .columnsGap(0)
+ .rowsGap(0)
+ .size({ width: "100%", height: "100%" })
+ }
+ }
+}
+```
+
+Recommendation: Reduce the redundant nesting of **\** containers. In this way, the number of components that each grid item needs to pass is three less, shortening the refresh and rendering time.
+
+```javascript
+// xxx.ets
+@Entry
+@Component
+struct AspectRatioExample {
+ @State children: Number[] = Array.from(Array(900), (v, k) => k);
+
+ build() {
+ Scroll() {
+ Grid() {
+ ForEach(this.children, (item) => {
+ GridItem() {
+ Text(item.toString())
+ }
+ }, item => item)
+ }
+ .columnsTemplate('1fr 1fr 1fr 1fr')
+ .columnsGap(0)
+ .rowsGap(0)
+ .size({ width: "100%", height: "100%" })
+ }
+ }
+}
+```
diff --git a/en/application-dev/quick-start/Readme-EN.md b/en/application-dev/quick-start/Readme-EN.md
index 7e6d0acac8ef49b1d6cb38a294d490c6f9a6144c..1d079b36d7af3cf7682659edc9362e6e802e258b 100644
--- a/en/application-dev/quick-start/Readme-EN.md
+++ b/en/application-dev/quick-start/Readme-EN.md
@@ -2,7 +2,7 @@
- Getting Started
- [Before You Start](start-overview.md)
- - [Getting Started with ArkTS in Stage Model](start-with-ets-stage.md)
+ - [Building the First ArkTS Application in Stage Model](start-with-ets-stage.md)
- Development Fundamentals
- Application Package Fundamentals
- [Application Package Overview](application-package-overview.md)
@@ -41,8 +41,8 @@
- [Resource Categories and Access](resource-categories-and-access.md)
- Learning ArkTS
- [Getting Started with ArkTS](arkts-get-started.md)
- - [Introduction to ArkTS](arkts/introduction-to-arkts.md)
- - [TypeScript to ArkTS Migration Guide](arkts/typescript-to-arkts-migration-guide.md)
+ - [Introduction to ArkTS](introduction-to-arkts.md)
+ - [TypeScript to ArkTS Migration Guide](typescript-to-arkts-migration-guide.md)
- UI paradigms
- Basic Syntax
- [Basic Syntax Overview](arkts-basic-syntax-overview.md)
@@ -55,6 +55,7 @@
- [\@Styles Decorator: Definition of Resusable Styles](arkts-style.md)
- [\@Extend Decorator: Extension of Built-in Components](arkts-extend.md)
- [stateStyles Decorator: Polymorphic Style](arkts-statestyles.md)
+ - [\@AnimatableExtend Decorator: Definition of Animatable Attributes](arkts-animatable-extend.md)
- State Management
- [State Management Overview](arkts-state-management-overview.md)
- Component State Management
diff --git a/en/application-dev/quick-start/arkts-appstorage.md b/en/application-dev/quick-start/arkts-appstorage.md
index 50cbcf6aa0854fc901eb6bbf80b41da7c990eaa1..c1ebb9c91252d5b75a96b837e6f07bd2f1053a56 100644
--- a/en/application-dev/quick-start/arkts-appstorage.md
+++ b/en/application-dev/quick-start/arkts-appstorage.md
@@ -23,8 +23,7 @@ Selected state attributes of AppStorage can be synced with different data source
As mentioned above, if you want to establish a binding between AppStorage and a custom component, you'll need the \@StorageProp and \@StorageLink decorators. Use \@StorageProp(key) or \@StorageLink(key) to decorate variables in the component, where **key** identifies the attribute in AppStorage.
-When a custom component is initialized, the \@StorageProp(key)/\@StorageLink(key) decorated variable is initialized with the value of the attribute with the given key in AppStorage. Local initialization is mandatory. If an attribute with the given key is missing from AppStorage, it will be added with the stated initializing value. (Whether the attribute with the given key exists in AppStorage depends on the application logic.)
-
+When a custom component is initialized, the \@StorageProp(key)/\@StorageLink(key) decorated variable is initialized with the value of the attribute with the given key in AppStorage. Whether the attribute with the given key exists in AppStorage depends on the application logic. This means that the attribute with the given key may be missing from AppStorage. In light of this, local initialization is mandatory for the \@StorageProp(key)/\@StorageLink(key) decorated variable.
By decorating a variable with \@StorageProp(key), a one-way data synchronization is established with the attribute with the given key in AppStorage. A local change can be made, but it will not be synchronized to AppStorage. An update to the attribute with the given key in AppStorage will overwrite local changes.
@@ -193,9 +192,85 @@ struct CompA {
}
```
-### Persistent Subscription and Callback
+### Unrecommended: Using @StorageLink to Implement Event Notification
+
+Compared with the common mechanism for event notification, the two-way synchronization mechanism of @StorageLink and AppStorage is far less cost efficient and therefore not recommended. This is because AppStorage stores UI-related data, and its changes will cause costly UI refresh.
+
+In the following example, any tap event in the **TapImage** component will trigger a change of the **tapIndex** attribute. As @StorageLink establishes a two-way data synchronization with AppStorage, the local change is synchronized to AppStorage. As a result, all visible custom components owning the **tapIndex** attribute bound to AppStorage are notified to refresh the UI.
+
+
+```ts
+// xxx.ets
+class ViewData {
+ title: string;
+ uri: Resource;
+ color: Color = Color.Black;
+
+ constructor(title: string, uri: Resource) {
+ this.title = title;
+ this.uri = uri
+ }
+}
+
+@Entry
+@Component
+struct Gallery2 {
+ dataList: Array = [new ViewData('flower', $r('app.media.icon')), new ViewData('OMG', $r('app.media.icon')), new ViewData('OMG', $r('app.media.icon'))]
+ scroller: Scroller = new Scroller()
+
+ build() {
+ Column() {
+ Grid(this.scroller) {
+ ForEach(this.dataList, (item: ViewData, index?: number) => {
+ GridItem() {
+ TapImage({
+ uri: item.uri,
+ index: index
+ })
+ }.aspectRatio(1)
+
+ }, (item: ViewData, index?: number) => {
+ return JSON.stringify(item) + index;
+ })
+ }.columnsTemplate('1fr 1fr')
+ }
+
+ }
+}
+
+@Component
+export struct TapImage {
+ @StorageLink('tapIndex') @Watch('onTapIndexChange') tapIndex: number = -1;
+ @State tapColor: Color = Color.Black;
+ private index: number;
+ private uri: Resource;
+
+ // Check whether the component is selected.
+ onTapIndexChange() {
+ if (this.tapIndex >= 0 && this.index === this.tapIndex) {
+ console.info(`tapindex: ${this.tapIndex}, index: ${this.index}, red`)
+ this.tapColor = Color.Red;
+ } else {
+ console.info(`tapindex: ${this.tapIndex}, index: ${this.index}, black`)
+ this.tapColor = Color.Black;
+ }
+ }
-The persistent subscription and callback can help reduce overhead and enhance code readability.
+ build() {
+ Column() {
+ Image(this.uri)
+ .objectFit(ImageFit.Cover)
+ .onClick(() => {
+ this.tapIndex = this.index;
+ })
+ .border({ width: 5, style: BorderStyle.Dotted, color: this.tapColor })
+ }
+
+ }
+}
+```
+
+To implement event notification with less overhead and higher code readability, use **emit** instead, with which you can subscribe to an event and receive event callback.
```ts
@@ -294,10 +369,9 @@ export struct TapImage {
}
```
-The following example uses the message mechanism to subscribe to events. Because this mechanism can result in a large number of nodes to listen for and a long implementation time, it is not recommended.
-
+The preceding notification logic is simple. It can be simplified into a ternary expression as follows:
-```ts
+```
// xxx.ets
class ViewData {
title: string;
@@ -338,22 +412,11 @@ struct Gallery2 {
@Component
export struct TapImage {
- @StorageLink('tapIndex') @Watch('onTapIndexChange') tapIndex: number = -1;
+ @StorageLink('tapIndex') tapIndex: number = -1;
@State tapColor: Color = Color.Black;
private index: number;
private uri: Resource;
- // Check whether the component is selected.
- onTapIndexChange() {
- if (this.tapIndex >= 0 && this.index === this.tapIndex) {
- console.info(`tapindex: ${this.tapIndex}, index: ${this.index}, red`)
- this.tapColor = Color.Red;
- } else {
- console.info(`tapindex: ${this.tapIndex}, index: ${this.index}, black`)
- this.tapColor = Color.Black;
- }
- }
-
build() {
Column() {
Image(this.uri)
@@ -361,14 +424,18 @@ export struct TapImage {
.onClick(() => {
this.tapIndex = this.index;
})
- .border({ width: 5, style: BorderStyle.Dotted, color: this.tapColor })
+ .border({
+ width: 5,
+ style: BorderStyle.Dotted,
+ color: (this.tapIndex >= 0 && this.index === this.tapIndex) ? Color.Red : Color.Black
+ })
}
-
}
}
```
+
## Restrictions
When using AppStorage together with [PersistentStorage](arkts-persiststorage.md) and [Environment](arkts-environment.md), pay attention to the following:
@@ -377,5 +444,5 @@ When using AppStorage together with [PersistentStorage](arkts-persiststorage.md)
- A call to **Environment.EnvProp()** after creating the attribute in AppStorage will fail. This is because AppStorage already has an attribute with the same name, and the environment variable will not be written into AppStorage. Therefore, you are advised not to use the preset environment variable name in AppStorage.
-- Changes to the variables decorated by state decorators will cause UI re-render. If the changes are for message communication, rather than for UI re-render, the emitter mode is recommended. For the example, see [Persistent Subscription and Callback](#persistent-subscription-and-callback).
+- Changes to the variables decorated by state decorators will cause UI re-render. If the changes are for message communication, rather than for UI re-render, the emitter mode is recommended. For the example, see [Unrecommended: Using @StorageLink to Implement Event Notification](#unrecommended-using-storagelink-to-implement-event-notification).
diff --git a/en/application-dev/quick-start/arkts-builder.md b/en/application-dev/quick-start/arkts-builder.md
index 80a262fcd97a0dcf6808bf8cdb84bf78849cb0e1..ab1c53b103db98c49fa42a21f69adff6ea32b86b 100644
--- a/en/application-dev/quick-start/arkts-builder.md
+++ b/en/application-dev/quick-start/arkts-builder.md
@@ -21,14 +21,14 @@ Syntax:
```ts
-@Builder myBuilderFunction({ ... })
+@Builder MyBuilderFunction({ ... })
```
Usage:
```ts
-this.myBuilderFunction({ ... })
+this.MyBuilderFunction({ ... })
```
- Defining one or more custom builder (\@Builder decorated) functions inside a custom component is allowed. Such a custom builder function can be considered as a private, special type of member functions of that component.
@@ -66,7 +66,7 @@ There are two types of parameter passing for custom builder functions: [by-value
- The parameter type must be the same as the declared parameter type. The **undefined** or **null** constants as well as expressions evaluating to these values are not allowed.
-- All parameters are immutable inside the custom builder function. If mutability and synchronization of the mutation is required, the custom builder should be replaced by a custom component with a [@Link](arkts-link.md) decorated variable.
+- All parameters are immutable inside the@Builder decorated function.
- The \@Builder function body follows the same [syntax rules](arkts-create-custom-components.md#build-function) as the **build** function.
diff --git a/en/application-dev/quick-start/arkts-builderparam.md b/en/application-dev/quick-start/arkts-builderparam.md
index 66647f094bfa5e5e090dba5cb5b1f0af27850d5f..947c33b139cc9a529ffbe345ab0d3cbd01b73172 100644
--- a/en/application-dev/quick-start/arkts-builderparam.md
+++ b/en/application-dev/quick-start/arkts-builderparam.md
@@ -152,7 +152,7 @@ struct Parent {
```
-### Example of Component Initialization Through Trailing Closure
+### Component Initialization Through Trailing Closure
In a custom component, the \@BuilderParam decorated attribute can be initialized using a trailing closure. During initialization, the component name is followed by a pair of braces ({}) to form a trailing closure.
diff --git a/en/application-dev/quick-start/arkts-create-custom-components.md b/en/application-dev/quick-start/arkts-create-custom-components.md
index 9548ad942cbd5ba3a24e4bcfe57ab71a0fb37043..45efde654b917c333e52d1f0d294282569622c45 100644
--- a/en/application-dev/quick-start/arkts-create-custom-components.md
+++ b/en/application-dev/quick-start/arkts-create-custom-components.md
@@ -70,8 +70,6 @@ To fully understand the preceding example, a knowledge of the following concepts
- [Universal Style of a Custom Component](#universal-style-of-a-custom-component)
-- [Custom Attribute Methods](#custom-attribute-methods)
-
## Basic Structure of a Custom Component
@@ -106,6 +104,8 @@ To fully understand the preceding example, a knowledge of the following concepts
> **NOTE**
>
> Since API version 9, this decorator is supported in ArkTS widgets.
+ >
+ > Since API version 10, the \@Entry decorator accepts an optional parameter of type [LocalStorage](arkts-localstorage.md) or type [EntryOptions](#entryoptions10).
```ts
@Entry
@@ -114,6 +114,23 @@ To fully understand the preceding example, a knowledge of the following concepts
}
```
+ ### EntryOptions10+
+
+ Describes the named route options.
+
+ | Name | Type | Mandatory| Description |
+ | ------ | ------ | ---- | ------------------------------------------------------------ |
+ | routeName | string | No| Name of the target named route.|
+ | storage | [LocalStorage](arkts-localstorage.md) | No| Storage of page-level UI state.|
+
+ ```ts
+ @Entry({ routeName : 'myPage' })
+ @Component
+ struct MyComponent {
+ }
+ ```
+
+
- \@Recycle: A custom component decorated with \@Recycle can be reused.
> **NOTE**
@@ -328,68 +345,4 @@ struct MyComponent {
>
> When ArkUI sets styles for custom components, an invisible container component is set for **MyComponent2**. These styles are set on the container component instead of the **\** component of **MyComponent2**. As seen from the rendering result, the red background color is not directly applied to the button. Instead, it is applied to the container component that is invisible to users where the button is located.
-
-## Custom Attribute Methods
-
-Custom components do not support custom attribute methods. You can use the Controller capability to implement custom APIs.
-
-
-```ts
-// Custom controller
-export class MyComponentController {
- item: MyComponent = null;
-
- setItem(item: MyComponent) {
- this.item = item;
- }
-
- changeText(value: string) {
- this.item.value = value;
- }
-}
-
-// Custom component
-@Component
-export default struct MyComponent {
- public controller: MyComponentController = null;
- @State value: string = 'Hello World';
-
- build() {
- Column() {
- Text(this.value)
- .fontSize(50)
- }
- }
-
- aboutToAppear() {
- if (this.controller)
- this.controller.setItem (this); // Link to the controller.
- }
-}
-
-// Processing logic
-@Entry
-@Component
-struct StyleExample {
- controller = new MyComponentController();
-
- build() {
- Column() {
- MyComponent({ controller: this.controller })
- }
- .onClick(() => {
- this.controller.changeText('Text');
- })
- }
-}
-```
-
-In the preceding example:
-
-1. The **aboutToAppear** method of the **MyComponent** child component passes the current **this** pointer to the **item** member variable of **MyComponentController**.
-
-2. The **StyleExample** parent component holds a **Controller** instance and with which calls the **changeText** API of **Controller**. That is, the value of the state variable **value** of **MyComponent** is changed through the **this** pointer of the **MyComponent** child component held by the controller.
-
-Through the encapsulation of the controller, **MyComponent** exposes the **changeText** API. All instances that hold the controller can call the **changeText** API to change the value of the **MyComponent** state variable **value**.
-
diff --git a/en/application-dev/quick-start/arkts-environment.md b/en/application-dev/quick-start/arkts-environment.md
index 2f0718290460508c4510acc298fa85c855bbec26..ac80bd54590b0dffdfa6b3bf82351d27f09917a1 100644
--- a/en/application-dev/quick-start/arkts-environment.md
+++ b/en/application-dev/quick-start/arkts-environment.md
@@ -15,12 +15,11 @@ Environment is a singleton object created by the ArkUI framework at application
- Use **Environment.EnvProp** to save the environment variables of the device to AppStorage.
```ts
- // Save the language code of the device to AppStorage. The default value is en.
- // Whenever its value changes in the device environment, it will update its value in AppStorage.
+ // Save languageCode to AppStorage. The default value is en.
Environment.EnvProp('languageCode', 'en');
```
-- To keep a component variable updated with changes in the device environment, this variable should be decorated with \@StorageProp.
+- Decorate the variables with \@StorageProp to link them with components.
```ts
@StorageProp('languageCode') lang : string = 'en';
@@ -29,6 +28,7 @@ Environment is a singleton object created by the ArkUI framework at application
The chain of updates is as follows: Environment > AppStorage > Component.
> **NOTE**
+>
> An \@StorageProp decorated variable can be locally modified, but the change will not be updated to AppStorage. This is because the environment variable parameters are read-only to the application.
@@ -69,3 +69,29 @@ if (lang.get() === 'en') {
console.info('Hello!');
}
```
+
+
+## Restrictions
+
+
+Environment can be called only when the [UIContext](../reference/apis/js-apis-arkui-UIContext.md#uicontext), which can be obtained through [runScopedTask](../reference/apis/js-apis-arkui-UIContext.md#runscopedtask), is specified. If Environment is called otherwise, no device environment data can be obtained.
+
+
+```ts
+// EntryAbility.ts
+import UIAbility from '@ohos.app.ability.UIAbility';
+import window from '@ohos.window';
+
+export default class EntryAbility extends UIAbility {
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ windowStage.loadContent('pages/Index');
+ let window = windowStage.getMainWindow()
+ window.then(window => {
+ let uicontext = window.getUIContext()
+ uicontext.runScopedTask(() => {
+ Environment.EnvProp('languageCode', 'en');
+ })
+ })
+ }
+}
+```
diff --git a/en/application-dev/quick-start/arkts-localstorage.md b/en/application-dev/quick-start/arkts-localstorage.md
index 0116d2e18f9023d5769b6b0b67b561b41bb0e149..392dda8432319b5695c593de178c5193fcf2a976 100644
--- a/en/application-dev/quick-start/arkts-localstorage.md
+++ b/en/application-dev/quick-start/arkts-localstorage.md
@@ -36,7 +36,7 @@ LocalStorage provides two decorators based on the synchronization type of the co
## Restrictions
- Once created, the type of a named attribute cannot be changed. Subsequent calls to **Set** must set a value of same type.
-- LocalStorage provides page-level storage. The [GetShared](../reference/arkui-ts/ts-state-management.md#getshared9) API can only obtain the LocalStorage instance transferred through [windowStage.loadContent](../reference/apis/js-apis-window.md#loadcontent9) in the current stage. Otherwise, **undefined** is returned. Example: [Sharing a LocalStorage Instance from UIAbility to One or More Pages](#sharing-a-localstorage-instance-from-uiability-to-one-or-more-pages).
+- LocalStorage provides page-level storage. The [GetShared](../reference/arkui-ts/ts-state-management.md#getshared10) API can only obtain the LocalStorage instance passed through [windowStage.loadContent](../reference/apis/js-apis-window.md#loadcontent9) in the current stage. If the instance is not available, **undefined** is returned. For the example, see [Example of Sharing a LocalStorage Instance from UIAbility to One or More Pages](#example-of-sharing-a-localstorage-instance-from-uiability-to-one-or-more-pages).
## \@LocalStorageProp
@@ -300,9 +300,9 @@ struct CompA {
```
-### State Variable Synchronization Between Sibling Nodes
+### Example of Syncing State Variable Between Sibling Components
-This example shows how to use \@LocalStorageLink to create a two-way synchronization for the state between sibling nodes.
+This example shows how to use \@LocalStorageLink to create a two-way synchronization for the state between sibling components.
Check the changes in the **Parent** custom component.
@@ -377,7 +377,7 @@ Changes in the **Child** custom component:
```
-### Sharing a LocalStorage Instance from UIAbility to One or More Pages
+### Example of Sharing a LocalStorage Instance from UIAbility to One or More Pages
In the preceding examples, the LocalStorage instance is shared only in an \@Entry decorated component and its owning child component (a page). To enable a LocalStorage instance to be shared across pages, you can create a LocalStorage instance in the owning UIAbility and call windowStage.[loadContent](../reference/apis/js-apis-window.md#loadcontent9).
diff --git a/en/application-dev/quick-start/arkts-observed-and-objectlink.md b/en/application-dev/quick-start/arkts-observed-and-objectlink.md
index 61f1bd8ae476f5984405eed97fb127161bb131e2..a7e47fb63e57896158a6a03aaa6896bea7ac644f 100644
--- a/en/application-dev/quick-start/arkts-observed-and-objectlink.md
+++ b/en/application-dev/quick-start/arkts-observed-and-objectlink.md
@@ -162,6 +162,26 @@ class ClassB {
this.a = a;
}
}
+
+@Observed
+class ClassD {
+ public c: ClassC;
+
+ constructor(c: ClassC) {
+ this.c = c;
+ }
+}
+
+@Observed
+class ClassC extends ClassA {
+ public k: number;
+
+ constructor(k: number) {
+ // Invoke the parent class method to process k.
+ super(k);
+ this.k = k;
+ }
+}
```
@@ -169,60 +189,64 @@ class ClassB {
```ts
@Component
-struct ViewA {
- label: string = 'ViewA1';
- @ObjectLink a: ClassA;
+struct ViewC {
+ label: string = 'ViewC1';
+ @ObjectLink c: ClassC;
build() {
Row() {
- Button(`ViewA [${this.label}] this.a.c=${this.a.c} +1`)
- .onClick(() => {
- this.a.c += 1;
- })
- }
+ Column() {
+ Text(`ViewC [${this.label}] this.a.c = ${this.c.c}`)
+ .fontColor('#ffffffff')
+ .backgroundColor('#ff3fc4c4')
+ .height(50)
+ .borderRadius(25)
+ Button(`ViewC: this.c.c add 1`)
+ .backgroundColor('#ff7fcf58')
+ .onClick(() => {
+ this.c.c += 1;
+ console.log('this.c.c:' + this.c.c)
+ })
+ }
+ .width(300)
}
}
+}
@Entry
@Component
struct ViewB {
@State b: ClassB = new ClassB(new ClassA(0));
-
+ @State child : ClassD = new ClassD(new ClassC(0));
build() {
Column() {
- ViewA({ label: 'ViewA #1', a: this.b.a })
- ViewA({ label: 'ViewA #2', a: this.b.a })
-
- Button(`ViewB: this.b.a.c+= 1`)
- .onClick(() => {
- this.b.a.c += 1;
- })
- Button(`ViewB: this.b.a = new ClassA(0)`)
+ ViewC({ label: 'ViewC #3', c: this.child.c})
+ Button(`ViewC: this.child.c.c add 10`)
+ .backgroundColor('#ff7fcf58')
.onClick(() => {
- this.b.a = new ClassA(0);
- })
- Button(`ViewB: this.b = new ClassB(ClassA(0))`)
- .onClick(() => {
- this.b = new ClassB(new ClassA(0));
+ this.child.c.c += 10
+ console.log('this.child.c.c:' + this.child.c.c)
})
}
}
}
```
+The @Observed decorated **ClassC** class can observe changes in attributes inherited from the base class.
+
Event handlers in **ViewB**:
-- this.b.a = new ClassA(0) and this.b = new ClassB(new ClassA(0)): Change to the \@State decorated variable **b** and its attributes.
+- this.child.c = new ClassA(0) and this.b = new ClassB(new ClassA(0)): Change to the \@State decorated variable **b** and its attributes.
-- this.b.a.c = ... : Change at the second layer. Though [@State](arkts-state.md#observed-changes) cannot observe the change at the second layer, the change of an attribute of \@Observed decorated ClassA, which is attribute **c** in this example, can be observed by \@ObjectLink.
+- this.child.c.c = ... : Change at the second layer. Though [@State](arkts-state.md#observed-changes) cannot observe the change at the second layer, the change of an attribute of \@Observed decorated ClassA, which is attribute **c** in this example, can be observed by \@ObjectLink.
-Event handlers in **ViewA**:
+Event handle in **ViewC**:
-- this.a.c += 1: Changes to the \@ObjectLink decorated variable cause the button label to be updated. Unlike \@Prop, \@ObjectLink does not have a copy of its source. Instead, \@ObjectLink creates a reference to its source.
+- this.c.c += 1: Changes to the \@ObjectLink decorated variable **a** cause the button label to be updated. Unlike \@Prop, \@ObjectLink does not have a copy of its source. Instead, \@ObjectLink creates a reference to its source.
- The \@ObjectLink decorated variable is read-only. Assigning **this.a = new ClassA(...)** is not allowed. Once value assignment occurs, the reference to the data source is reset and the synchronization is interrupted.
@@ -297,7 +321,7 @@ struct ViewB {
2. ViewA({ label: ViewA this.arrA[first], a: this.arrA[0] }): The preceding update changes the first element in the array. Therefore, the **ViewA** component instance bound to **this.arrA[0]** is updated.
- this.arrA.push(new ClassA(0)): The change of this state variable triggers two updates with different effects.
- 1. ForEach: The newly added Class A object is unknown to the **ForEach** [itemGenerator](arkts-rendering-control-foreach.md#api-description). The item builder of **ForEach** will be executed to create a **View A** component instance.
+ 1. ForEach: The newly added **ClassA** object is unknown to the **ForEach** [itemGenerator](arkts-rendering-control-foreach.md#api-description). The item builder of **ForEach** will be executed to create a **ViewA** component instance.
2. ViewA({ label: ViewA this.arrA[last], a: this.arrA[this.arrA.length-1] }): The last item of the array is changed. As a result, the second **View A** component instance is changed. For **ViewA({ label: ViewA this.arrA[first], a: this.arrA[0] })**, a change to the array does not trigger a change to the array item, so the first **View A** component instance is not refreshed.
- this.arrA[Math.floor (this.arrA.length/2)].c: [@State](arkts-state.md#observed-changes) cannot observe changes at the second layer. However, as **ClassA** is decorated by \@Observed, the change of its attributes will be observed by \@ObjectLink.
diff --git a/en/application-dev/quick-start/arkts-persiststorage.md b/en/application-dev/quick-start/arkts-persiststorage.md
index 303402ac5a2dffe2537fa4b252a21fcfe31631ad..21c854c26557e5fcd5027623b0429b625d6c9c91 100644
--- a/en/application-dev/quick-start/arkts-persiststorage.md
+++ b/en/application-dev/quick-start/arkts-persiststorage.md
@@ -24,7 +24,7 @@ Persistence of data is a relatively slow operation. Applications should avoid th
The preceding situations may overload the change process of persisted data. As a result, the PersistentStorage implementation may limit the change frequency of persisted attributes.
-PersistentStorage is associated with UIContext and can be called to persist data only when [UIContext](../reference/apis/js-apis-arkui-UIContext.md#uicontext) is specified. The context can be identified in [runScopedTask](../reference/apis/js-apis-arkui-UIContext.md#runscopedtask).
+PersistentStorage can be called to persist data only when the [UIContext](../reference/apis/js-apis-arkui-UIContext.md#uicontext), which can be obtained through [runScopedTask](../reference/apis/js-apis-arkui-UIContext.md#runscopedtask), is specified.
## Application Scenarios
@@ -92,7 +92,7 @@ struct Index {
1. The state variable **\@StorageLink('aProp') aProp** is updated, triggering the **\** component to be re-rendered.
2. The two-way synchronization between the \@StorageLink decorated variable and AppStorage results in the change of the **\@StorageLink('aProp') aProp** being synchronized back to AppStorage.
3. The change of the **aProp** attribute in AppStorage triggers any other one-way or two-way bound variables to be updated. (In this example, there are no such other variables.)
- 4. Because the attribute corresponding to **aProp** has been persisted, the change of the **aProp** attribute in AppStorage triggers PersistentStorage to write the attribute and its changed value to the device disk.
+ 4. Because the attribute corresponding to **aProp** has been persisted, the change of the **aProp** attribute in AppStorage triggers PersistentStorage to write the attribute and its new value to the device disk.
- Subsequent application running:
1. **PersistentStorage.PersistProp('aProp', 47)** is called. A search for the **aProp** attribute on the PersistentStorage disk succeeds.
diff --git a/en/application-dev/quick-start/arkts-prop.md b/en/application-dev/quick-start/arkts-prop.md
index 968673943256251a8d35a842663d2976ee5b5019..9838e932ff4288d0ce385f50a89492136439b058 100644
--- a/en/application-dev/quick-start/arkts-prop.md
+++ b/en/application-dev/quick-start/arkts-prop.md
@@ -528,11 +528,11 @@ struct MyComponent {
}
Row() {
- Button('Click to change locally !').width(480).height(60).margin({ top: 10 })
+ Button('Click to change locally !').width(180).height(60).margin({ top: 10 })
.onClick(() => {
this.customCounter2++
})
- }.height(100).width(480)
+ }.height(100).width(180)
Row() {
Text(`Custom Local: ${this.customCounter2}`).width(90).height(40).fontColor('#FF0010')
@@ -563,7 +563,7 @@ struct MainProgram {
MyComponent({ customCounter: this.mainCounter })
// customCounter2 of the child component can also be initialized from the parent component. The value from the parent component overwrites the locally assigned value of customCounter2 during initialization.
MyComponent({ customCounter: this.mainCounter, customCounter2: this.mainCounter })
- }.width('40%')
+ }
}
}
}
diff --git a/en/application-dev/quick-start/arkts-rendering-control-foreach.md b/en/application-dev/quick-start/arkts-rendering-control-foreach.md
index 4c916bec86f9c9d22b9bdb60ca476f9cbdcd4846..dc6ae173f51df82fbc48f26df56368450fa6fa79 100644
--- a/en/application-dev/quick-start/arkts-rendering-control-foreach.md
+++ b/en/application-dev/quick-start/arkts-rendering-control-foreach.md
@@ -3,6 +3,9 @@
**ForEach** enables repeated content based on array-type data.
+> **NOTE**
+>
+> Since API version 9, this API is supported in ArkTS widgets.
## API Description
@@ -19,15 +22,15 @@ ForEach(
| Name | Type | Mandatory | Description |
| ------------- | ---------------------------------------- | ---- | ---------------------------------------- |
| arr | Array | Yes | An array, which can be empty, in which case no child component is created. The functions that return array-type values are also allowed, for example, **arr.slice (1, 3)**. The set functions cannot change any state variables including the array itself, such as **Array.splice**, **Array.sort**, and **Array.reverse**.|
-| itemGenerator | (item: any, index?: number) => void | Yes | A lambda function used to generate one or more child components for each data item in an array. Each component and its child component list must be contained in parentheses. **NOTE** - The type of the child component must be the one allowed inside the parent container component of **ForEach**. For example, a **\** child component is allowed only when the parent container component of **ForEach** is **\**. - The child build function is allowed to return an **if** or another **ForEach**. **ForEach** can be placed inside **if**. - The optional **index** parameter should only be specified in the function signature if used in its body.|
-| keyGenerator | (item: any, index?: number) => string | No | An anonymous function used to generate a unique and fixed key value for each data item in an array. This key-value generator is optional. However, for performance reasons, it is strongly recommended that the key-value generator be provided, so that the development framework can better identify array changes. For example, if no key-value generator is provided, a reverse of an array will result in rebuilding of all nodes in **ForEach**. **NOTE** - Two items inside the same array must never work out the same ID. - If **index** is not used, an item's ID must not change when the item's position within the array changes. However, if **index** is used, then the ID must change when the item is moved within the array. - When an item is replaced by a new one (with a different value), the ID of the replaced and the ID of the new item must be different. - When **index** is used in the build function, it should also be used in the ID generation function. - The ID generation function is not allowed to mutate any component state.|
+| itemGenerator | (item: any, index?: number) => void | Yes | A lambda function used to generate one or more child components for each data item in an array. Each component and its child component list must be contained in parentheses. **NOTE** - The type of the child component must be the one allowed inside the parent container component of **ForEach**. For example, a **\** child component is allowed only when the parent container component of **ForEach** is **\**.