提交 bb2960ef 编写于 作者: G Gloria

replaced application-dev (en) folder with that in master

Signed-off-by: wusongqing<wusongqing@huawei.com>
上级 abac74be
...@@ -149,198 +149,53 @@ The value of <*formal_param_attr*> can be **in**, **out**, or **inout**, indicat ...@@ -149,198 +149,53 @@ The value of <*formal_param_attr*> can be **in**, **out**, or **inout**, indicat
## How to Develop ## How to Develop
### Development Using C++ ### Obtaining IDL
On DevEco Studio, choose **Tools > SDK Manager** to view the local installation path of the OpenHarmony SDK. The following figure uses DevEco Studio 3.0.0.993 as an example.
![SDKpath](./figures/SDKpath.png)
![SDKpath](./figures/SDKpath2.png)
#### Creating an IDL File Go to the local installation path, choose **toolchains > 3.x.x.x** (the folder named after the version number), and check whether the executable file of IDL exists.
You can use C++ to create IDL files. An example IDL file is as follows:
```cpp > **NOTE**: Use the SDK of the latest version. The use of an earlier version may cause errors in some statements.
interface OHOS.IIdlTestService {
int TestIntTransaction([in] int data);
void TestStringTransaction([in] String data);
}
```
You can run the **./idl -gen-cpp -d dir -c dir/iTest.idl** command (**-d** indicates the output directory) to generate the interface file, stub file, and proxy file in the **dir** directory in the execution environment. The names of the generated interface class files are the same as that of the IDL file, except that the file name extensions are **.h** and **.cpp**. For example, the files generated for **IIdlTestService.idl** are **i_idl_test_service.h**, **idl_test_service_proxy.h**, **idl_test_service_stub.h**, **idl_test_service_proxy.cpp**, and **idl_test_service_stub.cpp**. If the executable file does not exist, download the SDK package from the mirror as instructed in the [Release Notes](../../release-notes). The following uses the [3.2 Beta3](../../release-notes/OpenHarmony-v3.2-beta3.md#acquiring-source-code-from-mirrors) as an example.
#### Exposing Interfaces on the Server For details about how to replace the SDK package, see [Guide to Switching to Full SDK](../quick-start/full-sdk-switch-guide.md).
The stub class generated by IDL is an abstract implementation of the interface class and declares all methods in the IDL file. After obtaining the executable file, perform subsequent development steps based on your scenario.
```cpp ### Development Using TS
#ifndef OHOS_IDLTESTSERVICESTUB_H
#define OHOS_IDLTESTSERVICESTUB_H
#include <iremote_stub.h>
#include "iidl_test_service.h"
namespace OHOS {
class IdlTestServiceStub : public IRemoteStub<IIdlTestService> {
public:
int OnRemoteRequest(
/* [in] */ uint32_t code,
/* [in] */ MessageParcel& data,
/* [out] */ MessageParcel& reply,
/* [in] */ MessageOption& option) override;
private:
static constexpr int COMMAND_TEST_INT_TRANSACTION = MIN_TRANSACTION_ID + 0;
static constexpr int COMMAND_TEST_STRING_TRANSACTION = MIN_TRANSACTION_ID + 1;
};
} // namespace OHOS
#endif // OHOS_IDLTESTSERVICESTUB_H
```
You need to inherit the interface class defined in the IDL file and implement the methods in the class. In addition, you need to register the defined services with SAMGR during service initialization. In the following code snippet, **TestService** inherits the **IdlTestServiceStub** interface class and implements the **TestIntTransaction** and **TestStringTransaction** methods. #### Creating an IDL File
```cpp You can use TS to create IDL files.
#ifndef OHOS_IPC_TEST_SERVICE_H
#define OHOS_IPC_TEST_SERVICE_H
#include "hilog/log.h"
#include "log_tags.h"
#include "idl_test_service_stub.h"
namespace OHOS {
class TestService : public IdlTestServiceStub {
public:
TestService();
~TestService();
static int Instantiate();
ErrCode TestIntTransaction(int data, int &rep) override;
ErrCode TestStringTransaction(const std::string& data) override;
private:
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestService" };
};
} // namespace OHOS
#endif // OHOS_IPC_TEST_SERVICE_H
```
The sample code for registering a service is as follows: For example, create a file named **IIdlTestService.idl** with the following content:
```cpp ```cpp
#include "test_service.h" interface OHOS.IIdlTestService {
int TestIntTransaction([in] int data);
#include <string_ex.h> void TestStringTransaction([in] String data);
}
#include "if_system_ability_manager.h"
#include "ipc_debug.h"
#include "ipc_skeleton.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
namespace OHOS {
using namespace OHOS::HiviewDFX;
int TestService::Instantiate()
{
ZLOGI(LABEL, "%{public}s call in", __func__);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (saMgr == nullptr) {
ZLOGE(LABEL, "%{public}s:fail to get Registry", __func__);
return -ENODEV;
}
sptr<IRemoteObject> newInstance = new TestService();
int result = saMgr->AddSystemAbility(IPC_TEST_SERVICE, newInstance);
ZLOGI(LABEL, "%{public}s: IPC_TEST_SERVICE result = %{public}d", __func__, result);
return result;
}
TestService::TestService()
{
}
TestService::~TestService()
{
}
ErrCode TestService::TestIntTransaction(int data, int &rep)
{
ZLOGE(LABEL, " TestService:read from client data = %{public}d", data);
rep = data + data;
return ERR_NONE;
}
ErrCode TestService::TestStringTransaction(const std::string &data)
{
ZLOGE(LABEL, "TestService:read string from client data = %{public}s", data.c_str());
return data.size();
}
} // namespace OHOS
``` ```
#### Calling Methods from the Client for IPC Run the **idl -gen-ts -d *dir* -c dir/IIdlTestService.idl** command in the folder where the executable file is located.
The C++ client obtains the service proxy defined in the system through SAMGR and then invokes the interface provided by the proxy. The sample code is as follows:
```cpp -*dir* next to **d** is the target output folder. For example, if the target output folder is **IIdlTestServiceTs**, run the **idl -gen-ts -d IIdlTestServiceTs -c IIdlTestServiceTs/IIdlTestService.idl** command in the folder where the executable file is located. The interface file, stub file, and proxy file are generated in the *dir* directory (**IIdlTestServiceTs** directory in this example) in the execution environment.
#include "test_client.h"
#include "if_system_ability_manager.h"
#include "ipc_debug.h"
#include "ipc_skeleton.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
namespace OHOS {
int TestClient::ConnectService()
{
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (saMgr == nullptr) {
ZLOGE(LABEL, "get registry fail");
return -1;
}
sptr<IRemoteObject> object = saMgr->GetSystemAbility(IPC_TEST_SERVICE); > **NOTE**: The generated interface class file name must be the same as that of the .idl file. Otherwise, an error occurs during code generation.
if (object != nullptr) {
ZLOGE(LABEL, "Got test Service object");
testService_ = (new (std::nothrow) IdlTestServiceProxy(object));
}
if (testService_ == nullptr) { For example, for an .idl file named **IIdlTestService.idl** and target output directory named **IIdlTestServiceTs**, the directory structure is similar to the following:
ZLOGE(LABEL, "Could not find Test Service!");
return -1;
}
return 0;
}
void TestClient::StartIntTransaction()
{
if (testService_ != nullptr) {
ZLOGE(LABEL, "StartIntTransaction");
[[maybe_unused]] int result = 0;
testService_->TestIntTransaction(1234, result); // 1234 : test number
ZLOGE(LABEL, "Rec result from server %{public}d.", result);
}
}
void TestClient::StartStringTransaction()
{
if (testService_ != nullptr) {
ZLOGI(LABEL, "StartIntTransaction");
testService_->TestStringTransaction("IDL Test");
}
}
} // namespace OHOS
``` ```
├── IIdlTestServiceTs # IDL code output folder
### Development Using TS │ ├── i_idl_test_service.ts # File generated
│ ├── idl_test_service_proxy.ts # File generated
#### Creating an IDL File │ ├── idl_test_service_stub.ts # File generated
│ └── IIdlTestService.idl # Constructed .idl file
You can use TS to create IDL files. An example IDL file is as follows: └── idl.exe # Executable file of IDL
```ts
interface OHOS.IIdlTestService {
int TestIntTransaction([in] int data);
void TestStringTransaction([in] String data);
}
``` ```
Run the **./idl -c IIdlTestService.idl -gen-ts -d /data/ts/** command (**-d** indicates the output directory) to generate the interface file, stub file, and proxy file in the **/data/ts** directory in the execution environment. The names of the generated interface class files are the same as that of the IDL file, except that the file name extension is **.ts**. For example, the files generated for the **IIdlTestService.idl** file are **i_idl_test_service.ts**, **idl_test_service_proxy.ts**, and **idl_test_service_stub.ts**.
#### Exposing Interfaces on the Server #### Exposing Interfaces on the Server
The stub class generated by IDL is an abstract implementation of the interface class and declares all methods in the IDL file. The stub class generated by IDL is an abstract implementation of the interface class and declares all methods in the IDL file.
...@@ -356,8 +211,8 @@ export default class IdlTestServiceStub extends rpc.RemoteObject implements IIdl ...@@ -356,8 +211,8 @@ export default class IdlTestServiceStub extends rpc.RemoteObject implements IIdl
super(des); super(des);
} }
onRemoteRequest(code: number, data, reply, option): boolean { async onRemoteRequestEx(code: number, data, reply, option): Promise<boolean> {
console.log("onRemoteRequest called, code = " + code); console.log("onRemoteRequestEx called, code = " + code);
switch(code) { switch(code) {
case IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION: { case IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION: {
let _data = data.readInt(); let _data = data.readInt();
...@@ -529,137 +384,3 @@ export default class MySequenceable { ...@@ -529,137 +384,3 @@ export default class MySequenceable {
private str; private str;
} }
``` ```
## How to Develop for Interworking Between C++ and TS
### TS Proxy and C++ Stub Development
#### C++ Service Object
1. Use C++ to construct an IDL file and run commands to generate interfaces, stub files, and proxy files.
2. Create a service object, inherit the interface class defined in the C++ stub file, and implement the methods in the class. An example is as follows:
```cpp
class IdlTestServiceImpl : public IdlTestServiceStub {
public:
IdlTestServiceImpl() = default;
virtual ~IdlTestServiceImpl() = default;
ErrCode TestIntTransaction(int _data, int& result) override
{
result = 256;
return ERR_OK;
}
ErrCode TestStringTransaction(const std::string& _data) override
{
return ERR_OK;
}
};
```
#### Native APIs in C++
C++ provides C++ service objects to TS in the format of native APIs. For example, C++ provides a **GetNativeObject** method, which is used to create an **IdlTestServiceImpl** instance. Using the **NAPI_ohos_rpc_CreateJsRemoteObject** method, you can create a JS remote object for the TS application.
```cpp
NativeValue* GetNativeObject(NativeEngine& engine, NativeCallbackInfo& info)
{
sptr<IdlTestServiceImpl> impl = new IdlTestServiceImpl();
napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(reinterpret_cast<napi_env>(&engine), impl);
NativeValue* nativeRemoteObject = reinterpret_cast<NativeValue*>(napiRemoteObject);
return nativeRemoteObject;
}
```
#### TS Proxy Object
Use TS to construct an IDL file and run commands to generate interfaces, stub files, and proxy files. An example proxy file is as follows:
```ts
import {testIntTransactionCallback} from "./i_idl_test_service";
import {testStringTransactionCallback} from "./i_idl_test_service";
import IIdlTestService from "./i_idl_test_service";
import rpc from "@ohos.rpc";
export default class IdlTestServiceProxy implements IIdlTestService {
constructor(proxy) {
this.proxy = proxy;
}
testIntTransaction(data: number, callback: testIntTransactionCallback): void
{
let _option = new rpc.MessageOption();
let _data = new rpc.MessageParcel();
let _reply = new rpc.MessageParcel();
_data.writeInt(data);
this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_INT_TRANSACTION, _data, _reply, _option).then(function(result) {
if (result.errCode == 0) {
let _errCode = result.reply.readInt();
if (_errCode != 0) {
let _returnValue = undefined;
callback(_errCode, _returnValue);
return;
}
let _returnValue = result.reply.readInt();
callback(_errCode, _returnValue);
} else {
console.log('sendRequest failed, errCode: ' + result.errCode);
}
})
}
testStringTransaction(data: string, callback: testStringTransactionCallback): void
{
let _option = new rpc.MessageOption();
let _data = new rpc.MessageParcel();
let _reply = new rpc.MessageParcel();
_data.writeString(data);
this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_STRING_TRANSACTION, _data, _reply, _option).then(function(result) {
if (result.errCode == 0) {
let _errCode = result.reply.readInt();
callback(_errCode);
} else {
console.log('sendRequest failed, errCode: ' + result.errCode);
}
})
}
static readonly COMMAND_TEST_INT_TRANSACTION = 1;
static readonly COMMAND_TEST_STRING_TRANSACTION = 2;
private proxy
}
```
#### Interworking Between TS and C++ Applications
1. The TS application invokes the native API to obtain the remote C++ service object.
2. Construct a TS proxy and transfers the remote C++ service object to it.
3. Use the TS proxy to call the method declared in the IDL file to implement the interworking between the TS proxy and C++ stub. The following is an example:
```ts
import IdlTestServiceProxy from './idl_test_service_proxy'
import nativeMgr from 'nativeManager';
function testIntTransactionCallback(errCode: number, returnValue: number)
{
console.log('errCode: ' + errCode + ' returnValue: ' + returnValue);
}
function testStringTransactionCallback(errCode: number)
{
console.log('errCode: ' + errCode);
}
function jsProxyTriggerCppStub()
{
let nativeObj = nativeMgr.GetNativeObject();
let tsProxy = new IdlTestServiceProxy(nativeObj);
// Call testIntTransaction.
tsProxy.testIntTransaction(10, testIntTransactionCallback);
// Call testStringTransaction.
tsProxy.testStringTransaction('test', testIntTransactionCallback);
}
```
...@@ -2,52 +2,87 @@ ...@@ -2,52 +2,87 @@
- [Application Development Overview](application-dev-guide.md) - [Application Development Overview](application-dev-guide.md)
- About OpenHarmony - About OpenHarmony
- [OpenHarmony Project](../OpenHarmony-Overview.md) - [OpenHarmony Project](../OpenHarmony-Overview.md)
- [Glossary](../glossary.md) - [Glossary](../glossary.md)
- [OpenHarmony Release Notes](../release-notes/Readme.md) - [OpenHarmony Release Notes](../release-notes/Readme.md)
- Quick Start - Quick Start
- Getting Started - Getting Started
- [Preparations](quick-start/start-overview.md) - [Before You Start](quick-start/start-overview.md)
- [Getting Started with ArkTS in Stage Model](quick-start/start-with-ets-stage.md) - [Getting Started with ArkTS in Stage Model](quick-start/start-with-ets-stage.md)
- [Getting Started with ArkTS in FA Model](quick-start/start-with-ets-fa.md) - [Getting Started with ArkTS in FA Model](quick-start/start-with-ets-fa.md)
- [Getting Started with JavaScript in FA Model](quick-start/start-with-js-fa.md) - [Getting Started with JavaScript in FA Model](quick-start/start-with-js-fa.md)
- Development Fundamentals - Development Fundamentals
- [Application Package Structure Configuration File (FA Model)](quick-start/package-structure.md) - Application Package Fundamentals
- [Application Package Structure Configuration File (Stage Model)](quick-start/stage-structure.md) - [Application Package Overview](quick-start/application-package-overview.md)
- [SysCap](quick-start/syscap.md) - Application Package Structure
- [Application Package Structure in Stage Model)](quick-start/application-package-structure-stage.md)
- [Application Package Structure in FA Model](quick-start/application-package-structure-fa.md)
- [HAR File Structure](quick-start/har-structure.md)
- Multi-HAP Mechanism
- [Multi-HAP Design Objectives](quick-start/multi-hap-objective.md)
- [Multi-HAP Build View](quick-start/multi-hap-build-view.md)
- [Multi-HAP Development, Debugging, Release, and Deployment Process](quick-start/multi-hap-release-deployment.md)
- [Multi-HAP Usage Rules](quick-start/multi-hap-rules.md)
- [Multi-HAP Operation Mechanism and Data Communication Modes](quick-start/multi-hap-principles.md)
- [Application Installation and Uninstallation Process](quick-start/application-package-install-uninstall.md)
- Application Configuration Files in Stage Model
- [Application Configuration File Overview (Stage Model)](quick-start/application-configuration-file-overview-stage.md)
- [app.json5 Configuration File](quick-start/app-configuration-file.md)
- [module.json5 Configuration File](quick-start/module-configuration-file.md)
- Application Configuration Files in FA Model
- [Application Configuration File Overview (FA Model)](quick-start/application-configuration-file-overview-fa.md)
- [Internal Structure of the app Tag](quick-start/app-structure.md)
- [Internal structure of deviceConfig Tag](quick-start/deviceconfig-structure.md)
- [Internal Structure of the module Tag](quick-start/module-structure.md)
- [Resource Categories and Access](quick-start/resource-categories-and-access.md)
- Learning ArkTS
- [Getting Started with ArkTS](quick-start/arkts-get-started.md)
- ArkTS Syntax (Declarative UI)
- [Basic UI Description](quick-start/arkts-basic-ui-description.md)
- State Management
- [Basic Concepts](quick-start/arkts-state-mgmt-concepts.md)
- [State Management with Page-level Variables](quick-start/arkts-state-mgmt-page-level.md)
- [State Management with Application-level Variables](quick-start/arkts-state-mgmt-application-level.md)
- [Dynamic UI Element Building](quick-start/arkts-dynamic-ui-elememt-building.md)
- [Rendering Control](quick-start/arkts-rendering-control.md)
- [Restrictions and Extensions](quick-start/arkts-restrictions-and-extensions.md)
- Development - Development
- [Ability Development](ability/Readme-EN.md) - [Application Models](application-models/Readme-EN.md)
- [UI Development](ui/Readme-EN.md) - [UI Development](ui/Readme-EN.md)
- [Common Event and Notification](notification/Readme-EN.md) - [Common Event and Notification](notification/Readme-EN.md)
- [Window Manager](windowmanager/Readme-EN.md) - [Window Manager](windowmanager/Readme-EN.md)
- [WebGL](webgl/Readme-EN.md) - [WebGL](webgl/Readme-EN.md)
- [Media](media/Readme-EN.md) - [Media](media/Readme-EN.md)
- [Security](security/Readme-EN.md) - [Security](security/Readme-EN.md)
- [Connectivity](connectivity/Readme-EN.md) - [Connectivity](connectivity/Readme-EN.md)
- [Data Management](database/Readme-EN.md) - [Data Management](database/Readme-EN.md)
- [File Management](file-management/Readme-EN.md) - [File Management](file-management/Readme-EN.md)
- [Telephony](telephony/Readme-EN.md) - [Telephony](telephony/Readme-EN.md)
- [Task Management](task-management/Readme-EN.md) - [Task Management](task-management/Readme-EN.md)
- [Device Management](device/Readme-EN.md) - [Device Management](device/Readme-EN.md)
- [Device Usage Statistics](device-usage-statistics/Readme-EN.md) - [Device Usage Statistics](device-usage-statistics/Readme-EN.md)
- [DFX](dfx/Readme-EN.md) - [DFX](dfx/Readme-EN.md)
- [Internationalization](internationalization/Readme-EN.md) - [Internationalization](internationalization/Readme-EN.md)
- [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md) - [Application Test](application-test/Readme-EN.md)
- [Using Native APIs in Application Projects](napi/Readme-EN.md) - [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md)
- [Using Native APIs in Application Projects](napi/Readme-EN.md)
- Tools - Tools
- [DevEco Studio (OpenHarmony) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md) - [DevEco Studio (OpenHarmony) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md)
- Hands-On Tutorials - Hands-On Tutorials
- [Samples](https://gitee.com/openharmony/applications_app_samples/blob/master/README.md) - [Samples](https://gitee.com/openharmony/applications_app_samples/blob/master/README.md)
- [Codelabs](https://gitee.com/openharmony/codelabs) - [Codelabs](https://gitee.com/openharmony/codelabs)
- API References - API References
- [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md) - [SystemCapability](reference/syscap.md)
- [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md) - [SystemCapability List](reference/syscap-list.md)
- APIs - [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md)
- [JS and TS APIs](reference/apis/Readme-EN.md) - [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md)
- Native APIs - [JS Service Widget UI Components](reference/js-service-widget-ui/Readme-EN.md)
- [Standard Libraries](reference/native-lib/third_party_libc/musl.md) - APIs
- [Node_API](reference/native-lib/third_party_napi/napi.md) - [ArkTS and JS APIs](reference/apis/Readme-EN.md)
- [Error Codes](reference/errorcodes/Readme-EN.md)
- Native APIs
- [Standard Libraries](reference/native-lib/third_party_libc/musl.md)
- [Node_API](reference/native-lib/third_party_napi/napi.md)
- [FAQs](faqs/Readme-EN.md) - [FAQs](faqs/Readme-EN.md)
- Contribution - Contribution
- [How to Contribute](../contribute/documentation-contribution.md) - [How to Contribute](../contribute/documentation-contribution.md)
...@@ -18,7 +18,7 @@ To facilitate your application development, we provide development guidelines fo ...@@ -18,7 +18,7 @@ To facilitate your application development, we provide development guidelines fo
First thing first, familiarize yourself with the two cornerstone frameworks in OpenHarmony applications: First thing first, familiarize yourself with the two cornerstone frameworks in OpenHarmony applications:
- Application framework: [Ability Development](ability/Readme-EN.md) - Application framework: [Application Models](application-models/Readme-EN.md)
- UI framework: [UI Development](ui/Readme-EN.md) - UI framework: [UI Development](ui/Readme-EN.md)
All applications should be developed on top of these frameworks. All applications should be developed on top of these frameworks.
...@@ -37,6 +37,7 @@ Then, equip yourself for developing the key features, with the following guideli ...@@ -37,6 +37,7 @@ Then, equip yourself for developing the key features, with the following guideli
- [Device Usage Statistics](device-usage-statistics/Readme-EN.md) - [Device Usage Statistics](device-usage-statistics/Readme-EN.md)
- [DFX](dfx/Readme-EN.md) - [DFX](dfx/Readme-EN.md)
- [Internationalization](internationalization/Readme-EN.md) - [Internationalization](internationalization/Readme-EN.md)
- [Application Test](application-test/Readme-EN.md)
- [IDL Specifications and User Guide](IDL/idl-guidelines.md) - [IDL Specifications and User Guide](IDL/idl-guidelines.md)
- [Using Native APIs in Application Projects](napi/Readme-EN.md) - [Using Native APIs in Application Projects](napi/Readme-EN.md)
...@@ -56,11 +57,11 @@ API references encompass all components and APIs available in OpenHarmony, helpi ...@@ -56,11 +57,11 @@ API references encompass all components and APIs available in OpenHarmony, helpi
They are organized as follows: They are organized as follows:
- [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md) - [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md)
- [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md)
- [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md) - [JS Service Widget UI Components](reference/js-service-widget-ui/Readme-EN.md)
- APIs - APIs
- [JS and TS APIs](reference/apis/Readme-EN.md) - [JS and TS APIs](reference/apis/Readme-EN.md)
- Native APIs - Native APIs
- [Standard Library](reference/native-lib/third_party_libc/musl.md) - [Standard Library](reference/native-lib/third_party_libc/musl.md)
- [Node_API](reference/native-lib/third_party_napi/napi.md) - [Node_API](reference/native-lib/third_party_napi/napi.md)
......
...@@ -18,7 +18,7 @@ To facilitate your application development, we provide development guidelines fo ...@@ -18,7 +18,7 @@ To facilitate your application development, we provide development guidelines fo
First thing first, familiarize yourself with the two cornerstone frameworks in OpenHarmony applications: First thing first, familiarize yourself with the two cornerstone frameworks in OpenHarmony applications:
- Application framework: [Ability Development](ability/fa-brief.md) - Application framework: [Application Models](application-models/application-model-composition.md)
- UI framework: [UI Development](ui/arkui-overview.md) - UI framework: [UI Development](ui/arkui-overview.md)
All applications should be developed on top of these frameworks. All applications should be developed on top of these frameworks.
...@@ -35,8 +35,9 @@ Then, equip yourself for developing the key features, with the following guideli ...@@ -35,8 +35,9 @@ Then, equip yourself for developing the key features, with the following guideli
- [Task Management](task-management/background-task-overview.md) - [Task Management](task-management/background-task-overview.md)
- [Device](device/usb-overview.md) - [Device](device/usb-overview.md)
- [Device Usage Statistics](device-usage-statistics/device-usage-statistics-overview.md) - [Device Usage Statistics](device-usage-statistics/device-usage-statistics-overview.md)
- [DFX](dfx/hiappevent-overview.md) - [DFX](dfx/hiappevent-guidelines.md)
- [Internationalization](internationalization/international-overview.md) - [Internationalization](internationalization/international-overview.md)
- [Application Test](application-test/arkxtest-guidelines.md)
- [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md) - [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md)
- [Using Native APIs in Application Projects](napi/napi-guidelines.md) - [Using Native APIs in Application Projects](napi/napi-guidelines.md)
...@@ -59,7 +60,9 @@ They are organized as follows: ...@@ -59,7 +60,9 @@ They are organized as follows:
- [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md) - [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md)
- [JS and TS APIs](reference/apis/js-apis-DataUriUtils.md) - [JS Service Widget UI Components](reference/js-service-widget-ui/Readme-EN.md)
- [JS and TS APIs](reference/apis/js-apis-ability-dataUriUtils.md)
- Native APIs - Native APIs
- [Standard Library](reference/native-lib/third_party_libc/musl.md) - [Standard Library](reference/native-lib/third_party_libc/musl.md)
......
# FAQs # FAQs
- [Programming Languages](faqs-language.md)
- [Ability Framework Development](faqs-ability.md) - [Ability Framework Development](faqs-ability.md)
- [Bundle Management Development](faqs-bundle.md) - [Bundle Management Development](faqs-bundle.md)
- [ArkUI (eTS) Development](faqs-ui-ets.md) - [ArkUI (ArkTS) Development](faqs-ui-ets.md)
- [ArkUI Web Component (ArkTS) Development](faqs-web-arkts.md)
- [ArkUI (JavaScript) Development](faqs-ui-js.md) - [ArkUI (JavaScript) Development](faqs-ui-js.md)
- [Common Event and Notification Development](faqs-event-notification.md)
- [Graphics and Image Development](faqs-graphics.md) - [Graphics and Image Development](faqs-graphics.md)
- [File Management Development](faqs-file-management.md) - [File Management Development](faqs-file-management.md)
- [Media Development](faqs-media.md) - [Media Development](faqs-media.md)
- [Network and Connection Development](faqs-connectivity.md) - [Network and Connection Development](faqs-connectivity.md)
- [Data Management Development](faqs-data-management.md) - [Data Management Development](faqs-data-management.md)
- [Device Management Development](faqs-device-management.md) - [Device Management Development](faqs-device-management.md)
- [DFX Development](faqs-dfx.md)
- [Intl Development](faqs-international.md)
- [Native API Usage](faqs-native.md) - [Native API Usage](faqs-native.md)
- [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md) - [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md)
- [hdc_std Command Usage](faqs-ide.md) - [IDE Usage](faqs-ide.md)
- [IDE Usage](faqs-hdc-std.md) - [hdc_std Command Usage](faqs-hdc-std.md)
- [Development Board](faqs-development-board.md) - [Development Board](faqs-development-board.md)
\ No newline at end of file
...@@ -60,7 +60,7 @@ Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9 ...@@ -60,7 +60,7 @@ Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Configure the **startWindowIcon** attribute under **abilities** in the **module.json5** file. Configure the **startWindowIcon** attribute under **abilities** in the **module.json5** file.
Reference: [Application Package Structure Configuration File](../quick-start/stage-structure.md) Reference: [Application Package Structure (Stage Model)](../quick-start/module-configuration-file.md)
Example: Example:
...@@ -83,17 +83,15 @@ Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9 ...@@ -83,17 +83,15 @@ Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Implement the **onConfigurationUpdated** callback in the **Ability** class. The callback is triggered when the system language, color mode, or display parameters (such as the orientation and density) change. Implement the **onConfigurationUpdated** callback in the **Ability** class. The callback is triggered when the system language, color mode, or display parameters (such as the orientation and density) change.
Reference: [Ability Development](../ability/stage-ability.md)
## Can I obtain the context through globalThis in the stage model? ## Can I obtain the context through globalThis in the stage model?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Do not use **globalThis** to obtain the context in the stage model. This is because all the processes of an application share a JS VM instance in the stage model. Multiple abilities can run on these processes and share the same global object. If **globalThis** is used, the context of different abilities of the same JS VM instance may be returned. Do not use **globalThis** to obtain the context in the stage model. This is because all the processes of an application share a JS VM instance in the stage model. Multiple abilities can run on these processes and share the same global object. If **globalThis** is used, the context of different abilities of the same JS VM instance may be returned.
For details about the recommended operation, see [Context in the Stage Model](../ability/context-userguide.md#context-in-the-stage-model). Reference of the recommended operation: [Context (Stage Model)](../application-models/application-context-stage.md)
## How do I obtain the HAP file installation path of application B from application A? ## How do I obtain the HAP installation path of application B from application A?
Applicable to: OpenHarmony SDK 3.0 or later, stage model of API version 9 Applicable to: OpenHarmony SDK 3.0 or later, stage model of API version 9
...@@ -109,7 +107,7 @@ The callee uses **AbilityContext.terminateSelfWithResult** to destroy its abilit ...@@ -109,7 +107,7 @@ The callee uses **AbilityContext.terminateSelfWithResult** to destroy its abilit
Applicable to: OpenHarmony SDK 3.2.5.5, FA model of API version 8 Applicable to: OpenHarmony SDK 3.2.5.5, FA model of API version 8
After a widget is added, the **onCreate()** lifecycle is triggered so that related user information (silent login) can be displayed even when the application is not started. However, users must manually add the widget after the application is installed. After a widget is added, the **oncreate()** lifecycle is triggered so that related user information (silent login) can be displayed even when the application is not started. However, users must manually add the widget after the application is installed.
## How do I obtain the context? ## How do I obtain the context?
...@@ -214,3 +212,5 @@ The following conditions must be met: ...@@ -214,3 +212,5 @@ The following conditions must be met:
1. Before the redirection to the previous page, a confirm dialog box will be displayed. Note that **router.disableAlertBeforeBackPage** is used to disable the display of a confirm dialog box before returning to the previous page (default), and **router.enableAlertBeforeBackPage** is used to enable the display. 1. Before the redirection to the previous page, a confirm dialog box will be displayed. Note that **router.disableAlertBeforeBackPage** is used to disable the display of a confirm dialog box before returning to the previous page (default), and **router.enableAlertBeforeBackPage** is used to enable the display.
2. The system return key is used. 2. The system return key is used.
<!--no_check-->
\ No newline at end of file
...@@ -21,7 +21,7 @@ Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9 ...@@ -21,7 +21,7 @@ Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Error code 28 refers to **CURLE_OPERATION_TIMEDOUT**, which means a cURL operation timeout. For details, see any HTTP status code description available. Error code 28 refers to **CURLE_OPERATION_TIMEDOUT**, which means a cURL operation timeout. For details, see any HTTP status code description available.
Reference: [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-http.md#httpresponse) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html) Reference: [Response Codes](../reference/apis/js-apis-http.md#responsecode) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html)
## What does error code 6 mean for the response of \@ohos.net.http.d.ts? ## What does error code 6 mean for the response of \@ohos.net.http.d.ts?
...@@ -30,4 +30,4 @@ Applicable to: OpenHarmony SDK 3.2.3.5 ...@@ -30,4 +30,4 @@ Applicable to: OpenHarmony SDK 3.2.3.5
Error code 6 indicates a failure to resolve the host in the address. You can ping the URL carried in the request to check whether the host is accessible. Error code 6 indicates a failure to resolve the host in the address. You can ping the URL carried in the request to check whether the host is accessible.
Reference: [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-http.md#httpresponse) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html) Reference: [Response Codes](../reference/apis/js-apis-http.md#responsecode) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html)
# Data Management Development # Data Management Development
## How Do I Save PixelMap Data to a Database?
## How Do I Save PixelMap data to a database?
Applicable to: OpenHarmony SDK 3.2.3.5 Applicable to: OpenHarmony SDK 3.2.3.5
You can convert a **PixelMap** into a **ArrayBuffer** and save the **ArrayBuffer** to your database. You can convert a **PixelMap** into an **ArrayBuffer** and save the **ArrayBuffer** to your database.
Reference: [readPixelsToBuffer](../reference/apis/js-apis-image.md#readpixelstobuffer7-1) Reference: [readPixelsToBuffer](../reference/apis/js-apis-image.md#readpixelstobuffer7-1)
...@@ -14,11 +12,65 @@ Reference: [readPixelsToBuffer](../reference/apis/js-apis-image.md#readpixelstob ...@@ -14,11 +12,65 @@ Reference: [readPixelsToBuffer](../reference/apis/js-apis-image.md#readpixelstob
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Run the hdc_std command to copy the .db, .db-shm, and .db-wal files from **/data/app/el2/100/database/Bundle name/entry/db/**, and then use the SQLite tool to open the files. Run the hdc_std command to copy the .db, .db-shm, and .db-wal files in **/data/app/el2/100/database/*bundleName*/entry/db/**, and then use the SQLite tool to open the files.
Example: Example:
``` ```
hdc_std file recv /data/app/el2/100/database/com.xxxx.xxxx/entry/db/test.db ./test.db hdc_std file recv /data/app/el2/100/database/com.xxxx.xxxx/entry/db/test.db ./test.db
``` ```
## Does the Database Has a Lock Mechanism?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
The distributed data service (DDS), relational database (RDB) store, and preferences provided OpenHarmony have a lock mechanism. You do not need to bother with the lock mechanism during the development.
## What Is a Transaction in an RDB Store?
Applicable to: all versions
When a large number of operations are performed in an RDB store, an unexpected exception may cause a failure of some data operations and loss of certain data. As a result, the application may become abnormal or even crash.
A transaction is a group of tasks serving as a single logical unit. It eliminates the failure of some of the operations and loss of associated data.
## What Data Types Does an RDB Store Support?
Applicable to: OpenHarmony SDK 3.0 or later, stage model of API version 9
An RDB store supports data of the number, string, and Boolean types. The number array supports data of the Double, Long, Float, Int, or Int64 type, with a maximum precision of 17 decimal digits.
## How Do I View Database db Files?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
1. Run the **hdc_std shell** command.
2. Obtain the absolute path or sandbox path of the database.
The absolute path is **/data/app/el2/<userId>/database/<bundleName>**. The default **<userId>** is **100**.
To obtain the sandbox path, run the **ps -ef | grep hapName** command to obtain the process ID of the application.
The database sandbox path is **/proc/<Application process ID>/root/data/storage/el2/database/**.
3. Run the **find ./ -name "\*.db"** command in the absolute path or sandbox path of the database.
## How Do I Store Long Text Data?
Applicable to: OpenHarmony SDK 3.2.5.5, API version 9
- Preferences support a string of up to 8192 bytes.
- The KV store supports a value of up to 4 MB.
Reference: [Preference Overview](../database/database-preference-overview.md) and [Distributed Data Service Overview](../database/database-mdds-overview.md)
## How Do I Develop DataShare on the Stage Model
Applicable to: OpenHarmony SDK 3.2.5.5, API version 9
The DataShare on the stage model cannot be used with the **DataAbility** for the FA model. The connected server application must be implemented by using **DataShareExtensionAbility**.
Reference: [DataShare Development](../database/database-datashare-guidelines.md)
# DFX Development
## How do I locate the fault when the application crashes?
Applicable to: OpenHarmony SDK 3.2.5.5
1. Locate the crash-related code based on the service log.
2. View the error information in the crash file, which is located at **/data/log/faultlog/faultlogger/**.
## Why cannot access controls in the UiTest test framework?
Applicable to: OpenHarmony SDK 3.2.5.5
Check whether **persist.ace.testmode.enabled** is turned on.
Run **hdc\_std shell param get persist.ace.testmode.enabled**.
If the value is **0**, run the **hdc\_std shell param set persist.ace.testmode.enabled 1** to enable the test mode.
## Why is private displayed in logs when the format parameter type of HiLog in C++ code is %d or %s?
When format parameters such as **%d** and **%s** are directly used, the standard system uses **private** to replace the actual data for printing by default to prevent data leakage. To print the actual data, replace **%d** with **%{public}d** or replace **%s** with **%{public}s**.
## What should I do if the hilog.debug log cannot be printed?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Run **hdc_std shell hilog -b D** to turn on the debugging switch.
## Is HiLog or console recommended for log printing? How do I set the domain if HiLog is used?
Applicable to: OpenHarmony SDK 3.2.2.5
You are advised to use the [HiLog](../reference/apis/js-apis-hilog.md) for log printing. For details about how to set the **domain** parameter, see the [Development Guide](../reference/apis/js-apis-hilog.md#hilogisloggable).
## What is the maximum length of a log record when HiLog is used? Is it configurable?
Applicable to: OpenHarmony SDK 3.2.2.5
The maximum length of a log record is 1,024 characters, and it is not changeable.
## Can I separate multiple strings by spaces in the tag parameter of the HiLog API?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
No. Separating multiple strings by spaces is not allowed.
## How do I print real data if HiLog does not contain data labeled by {public}?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
Run **hdc\_std shell hilog -p off** to disable logging of data labeled by {public}.
# Common Event and Notification Development
## What is the emitter data size limit?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
The emitter data size cannot exceed 10240.
## How do I implement the click-a-notification-to-open-an-application function?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
You can implement this function by setting the **wantAgent** attribute in the **NotificationRequest** parameter of the **Notification.publish** API.
Reference: [Notification](../reference/apis/js-apis-notification.md#notificationpublish) and [WantAgent](../reference/apis/js-apis-app-ability-wantAgent.md)
Example:
```ts
import WantAgent from '@ohos.wantAgent';
async function publishNotification() {
let wantAgentInfo = {
wants: [
{
bundleName: "com.example.myapplication",
abilityName: "EntryAbility",
}
],
operationType: WantAgent.OperationType.START_ABILITIES,
requestCode: 0,
}
const wantAgent = await WantAgent.getWantAgent(wantAgentInfo)
let contentType = Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT;
await Notification.publish({
content: {
contentType: contentType,
normal: {
title: "Test Title",
text: "Test content",
}
},
id: 1,
wantAgent: wantAgent
})
prompt.showToast ({ message: "Sent successfully." })
}
```
# File Management Development # File Management Development
## Does fileio.rmdir Delete Files Recursively?
Applicable to: OpenHarmony SDK 3.2.6.3, stage model of API version 9
## What If There is No Return Value or Error Captured After getAlbums Is Called? Yes. **fileio.rmdir** deletes files recursively.
## How Do I Create a File That Does Not Exist?
Applicable to: OpenHarmony SDK 3.2.6.3, stage model of API version 9
You can use **fileio.open(filePath, 0o100, 0o666)**. The second parameter **0o100** means to create a file if it does not exist. The third parameter **mode** must also be specified.
## What If "call fail callback fail, code: 202, data: json arguments illegal" Is Displayed?
Applicable to: OpenHarmony SDK 3.2.6.3, stage model of API version 9
When the **fileio** module is used to copy files, the file path cannot start with "file:///".
## How Do I Read Files Outside the App Sandbox?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
If the input parameter of the **fileio** API is **path**, only the sandbox directory of the current app obtained from the context can be accessed. To access data in other directories such as the user data, images, and videos, open the file as the data owner and operate with the file descriptor (FD) returned.
For example, to read or write a file in Media Library, perform the following steps:
1. Use **getFileAssets()** to obtain the **fileAsset** object.
2. Use **fileAsset.open()** to obtain the FD.
3. Use the obtained FD as the **fileIo** API parameter to read and write the file.
## What If the File Contains Garbled Characters?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Read the file content from the buffer, and decode the file content using **util.TextDecoder**.
Example:
```
import util from '@ohos.util'
async function readFile(path) {
let stream = fileio.createStreamSync(path, "r+");
let readOut = await stream.read(new ArrayBuffer(4096));
let textDecoder = new util.TextDecoder("utf-8", { ignoreBOM: true });
let buffer = new Uint8Array(readOut.buffer)
let readString = textDecoder.decode(buffer, { stream: false });
console.log ("[Demo] File content read: "+ readString);
}
```
## What Should I Do If There Is No Return Value or Error Captured After getAlbums Is Called?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
The **ohos.permission.READ_MEDIA** permission is required for calling **getAlbums**, and this permission needs user authorization. For details, see OpenHarmony [Application Permission List](../security/permission-list.md). The **ohos.permission.READ_MEDIA** is required for using **getAlbums()**. In addition, this permission needs user authorization. For details, see [OpenHarmony Permission List](../security/permission-list.md).
1. Configure the required permission in the **module.json5** file. 1. Configure the required permission in the **module.json5** file.
``` ```
"requestPermissions": [ "requestPermissions": [
{ {
...@@ -19,7 +69,7 @@ The **ohos.permission.READ_MEDIA** permission is required for calling **getAlbum ...@@ -19,7 +69,7 @@ The **ohos.permission.READ_MEDIA** permission is required for calling **getAlbum
``` ```
2. Add the code for user authorization before the **MainAbility.ts -> onWindowStageCreate** page is loaded. 2. Add the code for user authorization before the **MainAbility.ts -> onWindowStageCreate** page is loaded.
``` ```
private requestPermissions() { private requestPermissions() {
let permissionList: Array<string> = [ let permissionList: Array<string> = [
...@@ -34,3 +84,21 @@ The **ohos.permission.READ_MEDIA** permission is required for calling **getAlbum ...@@ -34,3 +84,21 @@ The **ohos.permission.READ_MEDIA** permission is required for calling **getAlbum
}) })
} }
``` ```
## What Do I Do If the App Crashes When FetchFileResult() Is Called Multiple Times?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Each time after the **FetchFileResult** object is called, call **FetchFileResult.close()** to release and invalidate the **FetchFileResult** object .
## What If An Error Is Reported by IDE When mediaLibrary.getMediaLibrary() Is Called in the Stage Model?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
In the stage model, use **mediaLibrary.getMediaLibrary(context: Context)** to obtain the media library instance.
## How Do I Sort the Data Returned by mediaLibrary.getFileAssets()?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Use the **order** attribute in **[MediaFetchOptions](../reference/apis/js-apis-medialibrary.md#mediafetchoptions7)** to sort the data returned.
# hdc_std Command Usage # hdc_std Command Usage
## Common Log Commands
## What are the commands commonly used for log management?
Applicable to: OpenHarmony SDK 3.2.2.5 Applicable to: OpenHarmony SDK 3.2.2.5
- Clearing logs: hdc_std shell hilog -r Clearing logs: hdc_std shell hilog -r
- Increasing the buffer size to 20 MB: hdc_std shell hilog -G 20M Increasing the buffer size to 20 MB: hdc_std shell hilog -G 20M
- Capturing logs: hdc_std shell hilog &gt; log.txt
Capturing logs: hdc_std shell hilog &gt; log.txt
## What should I do to avoid log flow control? ## What should I do to avoid log flow control?
...@@ -27,43 +24,64 @@ Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 ...@@ -27,43 +24,64 @@ Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
After performing the preceding operations, restart the DevEco Studio. After performing the preceding operations, restart the DevEco Studio.
## What should I do if the HAP installed on the development board through the IDE cannot be opened?
## Is HiLog or Console recommended for log printing? How do I set the domain if HiLog is used? Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Applicable to: OpenHarmony SDK 3.2.2.5 Check whether the SDK version is consistent with the system version on the development board. You are advised to use the SDK version and system version that are released on the same day.
[HiLog](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-hilog.md) is recommended for an application to print logs. For details about domain setting, see [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-hilog.md#hilogisloggable). ## How do I upload files using the hdc command?
Applicable to: OpenHarmony SDK 3.2.2.5
## What is the maximum length of a log record when HiLog is used? Is it configurable? Run the **hdc_std file send** command.
Applicable to: OpenHarmony SDK 3.2.2.5 ## How do I prevent the screen of the RK3568 development board from turning off?
The maximum length of a log record is 1,024 characters, and it is not changeable. Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Run the **hdc_std shell "power-shell setmode 602"** command.
## What should I do if a HAP package cannot be opened after being installed on the development board using the IDE? ## How do I start an ability using the hdc command?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Check whether the SDK version is consistent with the system version on the development board. You are advised to use the SDK version and system version that are released on the same day. Run the **hdc\_std shell aa start -a AbilityName -b bundleName -m moduleName** command.
## How do I change the read and write permissions on a file directory on the development board?
## How do I upload files using an hdc command? Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9
Run the **hdc\_std shell mount -o remount,rw /** command.
## What should I do if the error message "Unknown file option -r" is displayed when hdc_std file recv is run?
Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9
1. Use the the hdc tool in the device image or SDK of the same version.
2. Remove any Chinese characters or spaces from the directory specified for the hdc tool.
## How do I uninstall an application using the hdc command?
Applicable to: OpenHarmony SDK 3.2.2.5 Applicable to: OpenHarmony SDK 3.2.2.5
Run the **hdc_std file send** command. Run the **hdc\_std uninstall [-k] [package_name]** command.
## How do I prevent the screen of the RK3568 development board from turning off? ## How do I check whether the system is 32-bit or 64-bit?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.5
Run the **hdc_std shell "power-shell setmode 602"** command. Run the **hdc\_std shell getconf LONG_BIT** command.
If **64** is returned, the system is a 64-bit one. Otherwise, the system is a 32-bit one.
## How do I start an ability using an hdc command? ## How do I view the component tree structure?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.5
1. Run the **hdc\_std shell** command to launch the CLI.
2. Run the **aa dump -a** command to find **abilityID**.
Run the **hdc_std shell aa start -a AbilityName -b bundleName -m moduleName** command. 3. Run the **aa dump -i [abilityID] -c -render** command to view the component tree.
# IDE Usage # IDE Usage
## What should I do if the error message "npm ERR! code SELF_SIGNED_CERT_IN_CHAIN" is displayed?
## What should do if the error message "npm ERR! code SELF_SIGNED_CERT_IN_CHAIN" is displayed?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
1. Run **npm config set strict-ssl=false** on the DevEco Studio terminal. 1. Run **npm config set strict-ssl=false** on the DevEco Studio terminal.
2. Run the **npm install** on the DevEco Studio terminal. 2. Run **npm install** on the DevEco Studio terminal.
## After manual updating of the DevEco Studio SDK, the error message "Cannot find module 'xxx\ets\x.x.x.x\build-tools\ets-loader\node_modules\webpack\bin\webpack.js'" is displayed during HAP building. What should I do? ## After manual updating of a DevEco Studio SDK, the error message "Cannot find module 'xxx\ets\x.x.x.x\build-tools\ArkTS-loader\node_modules\webpack\bin\webpack.js'" is displayed during HAP building. What should I do?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
1. Run **npm install** in the **ets\x.x.x.x\build-tools\ets-loader** directory of the SDK. 1. Run **npm install** in the **ets\x.x.x.x\build-tools\ets-loader** directory of the SDK.
2. Run **npm install** in the **js\x.x.x.x\build-tools\ace-loader** directory of the SDK. 2. Run **npm install** in the **js\x.x.x.x\build-tools\ace-loader** directory of the SDK. Perform HAP building again.
## How do I pack a HAP file through the command line?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Method 1: Run **hvigor assembleHap**.
Method 2: In **scripts** of the project **package.json** file, define the build task script and run **npm buildOhosHaps**. The **buildOhosHaps** field can be customized.
```
"scripts": {
"buildOhosHaps": "hvigor assembleHap"
},
```
## How do I select API version 9 when creating a project in DevEco Studio?
Applicable to: DevEco Studio 3.0 Beta4 3.0.0.993(B06)
When creating a project in DevEco Studio, make sure you are on the **OpenHarmony** tab page.
## What should I do if no callback is received and no error code is returned for downloads?
Applicable to: all versions
1. Re-install hdc_std and set up the device connection again.
2. Run **hdc_std shell hilog -Q pidoff** to disable log log flow control.
## What should I do if the "error: unknow option. usage: aa start \<options>" message is displayed after I click Run in DevEco Studio?
Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9
This issue occurs when the parameter in the **aa** command is invalid and therefore the target application fails to be opened.
To fix this issue, use either of the following methods:
1. Make sure the SDK version and the OS version are the same.
2. Touch the application icon on the device to manually open the application.
## What should I do if "The hdc_std version of the SDK does not match the hdcd version of the device." message is displayed when I run an application in DevEco Studio?
Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9
This issue occurs when the hdc and hdcd versions do not match. Update Dev Eco Studio to 3.0.1.993 or later.
After the update, Dev Eco Studio will still indicate the version mismatch, but will not block the running.
## How do I add a custom .d.ts file to the OpenHarmony SDK?
Applicable to: OpenHarmony SDK 3.1.7.7, FA model of API version 8
Name the .d.ts file **@ohos.xxxx.d.ts**, save it to the SDK path, and restart Dev Eco Studio.
A code notification is displayed when the file is imported.
## How do I switch to the full SDK?
Applicable to: OpenHarmony SDK 3.2.7.5
3. Perform HAP building again. Follow the instructions in [Guide to Switching to Full SDK](../quick-start/full-sdk-switch-guide.md).
# Intl Development
## How resources in AppScope, such as images and text, are referenced?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Resources are referenced in the **$r('app.type.name')** format. Where, **type** indicates the resource type, such as color, string, and media, and **name** indicates the resource name.
## How do I convert the resource type to string?
Applicable to: OpenHarmony SDK3.0, stage model of API version 9
If the resource type is set to **string**, the qualifier directory can be set as **this.context.resourceManager.getStringSync(\\$r('app.string.test').id)** and can be converted synchronously. The **\$r('app.string.test', 2)** mode is not supported. For more usage methods, see [Resource Manager](../reference/apis/js-apis-resource-manager.md#getstringsync9).
## Why should I do if the constants referenced by $ in the form_config.json file does not take effect?
Applicable to: OpenHarmony SDK 3.2.6.5, API9 Stage model
In the **form\_config.json** file, **$** cannot be used to reference constants.
# Programming Languages
## What are the restrictions on using generator functions in TypeScript?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Below are the restrictions on using generator functions in TypeScript:
- Expressions can be used only in character strings (in the ${expression} format), **if** conditions, **ForEach** parameters, and component parameters.
- No expressions should cause any application state variables (including **@State**, **@Link**, and **@Prop**) to change. Otherwise, undefined and potentially unstable framework behavior may occur.
- The generator function cannot contain local variables.
None of the above restrictions apply to anonymous function implementations of event handlers (such as **onClick**).
Negative example:
```
build() {
let a: number = 1 // invalid: variable declaration not allowed
Column() {
Text('Hello ${this.myName.toUpperCase()}') // ok.
ForEach(this.arr.reverse(), ..., ...) // invalid: Array.reverse modifies the @State array variable in place
}
buildSpecial() // invalid: no function calls
Text(this.calcTextValue()) // this function call is ok.
}
```
## How do I dynamically replace the %s placeholder in a resource file?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
In an application, you can replace the %s placeholder by using the second parameter in **$r('app.string.xx')**, which is used to reference application resources.
Example:
```
build() {
//do something
// The second parameter indicates the referenced string resource, which can be used to replace the %s placeholder.
Text($r('app.string.entry_desc','aaa'))
.fontSize(100)
.fontColor(Color.Black)
//do something
}
```
## How do I read an XML file in Resource and convert data in it to the string type?
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
1. Obtain Uint8Array data by calling the **RawFile** API of **resourceManager**.
2. Convert the Uint8Array data to strings by calling the **String.fromCharCode** API.
Reference: [Resource Manager](../reference/apis/js-apis-resource-manager.md)
Example:
```
resourceManager.getRawFile(path, (error, value) => {
if (error != null) {
console.log("error is " + error);
} else {
let rawFile = value;
let xml = String.fromCharCode.apply(null, rawFile)
}
});
```
## How do I convert a Resource object to the string type?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Use the **resourceManager.getString()** API of the **@ohos.resourceManager** module.
Reference: [Resource Manager](../reference/apis/js-apis-resource-manager.md#getstring)
## What should I do if the global static variables of a class do not work?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Objects imported to abilities and pages are packaged into two different closures, that is, two global objects. In this case, a static variable referenced by the abilities is not the same object as that referenced by the pages. Therefore, global variables cannot be defined by defining static variables in the class. You are advised to use AppStorage to manage global variables.
Reference: [State Management with Application-level Variables](../quick-start/arkts-state-mgmt-application-level.md)
## How do I obtain resources in the stage model?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
The stage model allows an application to obtain a **ResourceManager** object based on **context** and call its resource management APIs without first importing the required bundle. This method, however, is not applicable to the FA model.
Example:
```
const context = getContext(this) as any
context
.resourceManager
.getString($r('app.string.entry_desc').id)
.then(value => {
this.message = value.toString()
})
```
## How do I obtain data through an API before page loading?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
In the **aboutToAppear** function, use an asynchronous API to obtain page data and **@State** to decorate related variables. After the data is obtained, the page is automatically refreshed based on the variables.
```
@Entry
@Component
struct Test6Page {
// After the data is obtained, the page is automatically refreshed.
@State message: string = 'loading.....'
aboutToAppear(){
// Simulate an asynchronous API to obtain data.
setTimeout(()=>{
this.message = 'new msg'
},3000)
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
```
## Do the worker thread and the main thread run in the same global context?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
No. The worker thread and the main thread are not in the same global context. They interact with each other in data communication mode.
## Which API is used for URL encoding in OpenHarmony?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
The global function **encodeURI** is used for URI encoding, and **decodeURI** is used for URI decoding. For example, a space character is encoded as %20.
## Does OpenHarmony provide any API for parsing XML files?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
Yes. The **convert** API of the **convertxml** module can be used to convert XML text into JavaScript objects.
Reference: [@ohos.convertxml](../reference/apis/js-apis-convertxml.md)
## How do I configure application icons to be used across devices?
Applicable to: OpenHarmony SDK 3.0, stage model of API version 9
Use resource qualifiers to configure application icons to be used across devices.
## Can placeholders be configured in the string.json file of the stage model?
Applicable to: OpenHarmony SDK 3.2.6.3, stage model of API version 9
The **string.json** file does not support placeholders. As an alternative, you can define variables on the target page and combine these variables and **Resource** objects.
## Is there any difference between the OpenHarmony API systemTime.getCurrentTime() and the JS API new Date().getTime() API?
Applicable to: OpenHarmony SDK 3.2.6.3, stage model of API version 9
Similar to **new Date().getTime()**, **systemTime.getCurrentTime(false)** returns the number of milliseconds that have elapsed since the Unix epoch. **systemTime.getCurrentTime(true)** returns the number of nanoseconds that have elapsed since the Unix epoch. The system time is used in both APIs.
## How do I define @BuilderParam decorated attributes based on the value assigned to them?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
If no parameter is passed when assigning a value to the **@BuilderParam** decorated attribute (for example, **content: this.specificParam**), define the type of the attribute as a function without a return value (for example, **@BuilderParam content: () =&gt; voi**). If any parameter is passed when assigning a value to the **@BuilderParam** decorated attribute (for example, **callContent: this.specificParam1("111")**), define the type of the attribute as **any** (for example, **@BuilderParam callContent: any**). For details, see [BuilderParam](../quick-start/arkts-dynamic-ui-elememt-building.md#builderparam8).
## How does ArkTS convert a string into a byte array?
Applicable to: all versions
Refer to the following code:
```
function stringToByte(str) {
var bytes = new Array();
var len,c;
len = str.length;
for(var i = 0;i<len;i++) {
c = str.charCodeAt(i);
if( c >= 0x010000 && c<= 0x10FFFF) {
bytes.push(((c>>18) & 0x07) | 0xf0);
bytes.push(((c>>12) & 0x3F) | 0x80);
bytes.push(((c>>6) & 0x3f) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if(c >= 0x000800 && c<= 0x00FFF){
bytes.push(((c>>12) & 0x07) | 0xf0);
bytes.push(((c>>6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if(c >= 0x000800 && c<= 0x0007FF) {
bytes.push(((c>>6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF)
}
}
return bytes;
}
```
## What do I do if the "Too many wokers, the number of worker exceeds the maximum" message is displayed during worker creation?
Applicable to: OpenHarmony SDK 3.2.6.5
An application allows for a maximum of seven workers. Therefore, use the **termiate** API to release workers when they are not needed.
Reference: [@ohos.worker](../reference/apis/js-apis-worker.md#terminate)
## What is the recommended multithreading solution on OpenHarmony?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
OpenHarmony recommends that worker threads be used for multithreading.
Reference: [@ohos.worker](../reference/apis/js-apis-worker.md)
## What is the difference between a @Builder decorated method and other methods?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
If the **@Builder** decorated method uses a custom component, this component is re-created each time the method is called.
## Why is the callback registered through @Watch not triggered when the object attributes of an array change?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
As with **@State**, the callback registered through **@Watch** can be used to listen for only one layer of data changes. If the object attributes of the array changes at the inner layer, the callback will not be triggered.
## How do I listen for in-depth changes of @State decorated variables?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
To listen for in-depth changes of **@State** decorated variables, you can use **@Observed** and **@ObjectLink** decorators.
Reference: [@Observed and @ObjectLink](../quick-start/arkts-state-mgmt-page-level.md#observed-and-objectlink)
## How do I implement character string encoding and decoding?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
You can use **TextEncoder** and **TextDecoder** provided by the **util** module.
Reference: [TextEncoder](../reference/apis/js-apis-util.md#textencoder) and [TextDecoder](../reference/apis/js-apis-util.md#textdecoder)
## How do i import and export namespaces?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
- Exporting namespaces
```
namespace Util{
export function getTime(){
return Date.now()
}
}
export default Util
```
- Importing namespaces
```
import Util from './util'
Util.getTime()
```
## Can relational database operations be performed in the worker thread?
Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9
No. Relational database operations cannot be performed in the worker thread.
<!--no_check-->
\ No newline at end of file
# ArkUI Web Component (ArkTS) Development
## What is the domStorageAccess attribute of the \<Web> component used for?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
The **domStorageAccess** attribute specifies whether to enable the DOM Storage API, which is disabled by default and provides **localStorage**, but not **sessionStorage**.
## How do I check the online status on the HTML page loaded by the \<Web> component?
Applicable to: OpenHarmony SDK 3.2.7.5, stage model of API version 9
1. Configure the **ohos.permission.INTERNET** and **ohos.permission.GET_NETWORK_INFO** application permissions.
2. Obtain the online status through **window.navigator.onLine** on the HTML page.
## What should I do if the UserAgent string cannot be used in concatenation before the initial HTML5 page loading by the \<Web> component?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
By default, the **UserAgent** string is obtained through the **WebController**. A **WebController** object can control only one **\<Web>** component, and methods on the **WebController** can only be called by the **\<Web>** component bound to it. To concatenate the default **UserAgent** string and a custom string before the initial page loading, perform the following:
1. Use **@State** to define the initial **userAgent** and bind it to the **\<Web>** component.
2. In the **onUrlLoadIntercept** callback of the **\<Web>** component, use **WebController** to obtain the default **userAgent** string and modify the **userAgent** bound to the **\<Web>** component.
The code snippet is as follows:
```
@Entry
@Component
struct Index {
private controller: WebController = new WebController()
@State userAgentPa: string = ''
build() {
Row() {
Column() {
Web({ src: 'www.example.com', controller: this.controller })
.width('100%')
.userAgent(this.userAgentPa)
.onUrlLoadIntercept((event) => {
let userAgent = this.controller.getDefaultUserAgent();
this.userAgentPa = userAgent + ' 111111111'
console.log("userAgent onUrlLoadIntercept: " + userAgent);
return false;
})
}
.width('100%').alignItems(HorizontalAlign.Start).backgroundColor(Color.Green)
}
.height('100%')
}
}
```
## Should the logic for loading the lottie animation be written in the onAppear or onReady function?
Applicable to: OpenHarmony SDK 3.2.6.5, stage model of API version 9
The logic for loading the lottie animation must be written in the **onReady** function. The **onReady** function is triggered when the canvas is ready, while the **onAppear** function is triggered when the canvas is displayed.
## Do I need to invoke the refresh API after invoking deleteJavaScriptRegister?
Applicable to: all versions
No. This operation is not needed.
## How do I pass data from a page to the \<Web> component?
Applicable to: OpenHarmony SDK 3.2.7.5, stage model of API version 9
1. Use **WebController** to create two message ports: message port 1 and message port 0.
2. Send message port 1 to the HTML side, which can then save and use the port.
3. Register a callback for message port 0 on the application side.
4. Use message port 0 on the application side to send messages to message port 1 on the HTML side.
Reference: [Web](../reference/arkui-ts/ts-basic-components-web.md#postmessage9)
...@@ -3,4 +3,7 @@ ...@@ -3,4 +3,7 @@
- [MediaLibrary Overview](medialibrary-overview.md) - [MediaLibrary Overview](medialibrary-overview.md)
- [Media Asset Management](medialibrary-resource-guidelines.md) - [Media Asset Management](medialibrary-resource-guidelines.md)
- [File Path Management](medialibrary-filepath-guidelines.md) - [File Path Management](medialibrary-filepath-guidelines.md)
- [Album Management](medialibrary-album-guidelines.md) - [Album Management](medialibrary-album-guidelines.md)
\ No newline at end of file
- File Access Framework
- [File Access Framework Overview](file-access-framework-overview.md)
# File Access Framework Overview
On devices running OpenHarmony 3.2 (API version 9) or later, applications can access public files on the local device, remote device, and external storage device, as well as files shared by multiple users, based on the File Access Framework (FAF).
To ensure user data privacy, this framework allows users to create, open, delete, rename, and move files on the file access server only through the **File Manager** and **File Picker** applications.
The user data of an application is stored on the device even after the application is uninstalled.
If a system application needs to access public files on the local device, use [File Path Management](medialibrary-filepath-guidelines.md).
> **NOTE**
> 1. For a non-management system application, for example, **Gallery**, use the **mediaLibrary** APIs for direct file operation.
> 2. In principle, do not mix use the FAF APIs with the mediaLibrary APIs.
## FAF Mechanism
Based on the OpenHarmony [ExtensionAbility mechanism](../application-models/extensionability-overview.md), the FAF provides unified APIs for external systems. With these APIs, applications can preview and operate public files to implement their own logic.
You can visit the [source repository](https://gitee.com/openharmony/filemanagement_user_file_service) for more details.
The following figure shows the FAF-based file operation process.
**Figure 1** Hierarchy of public file operations
![](figures/public-file-operation.png)
- **File access client**: an application that needs to access or operate public files. By starting the file selector application, it enables users to perform file operations on the UI.
- **File selector application**: a system application that allows users to access all shared datasets. You can use the FAF APIs to operate the datasets.
- **File access server**: a service that supports dataset sharing in the system. Currently, [UserFileManager](https://gitee.com/openharmony/multimedia_medialibrary_standard) and ExternalFileManager are available. UserFileManager manages datasets on local disks and distributed devices, and ExternalFileManager manages datasets on external storage devices such as SD cards and USB flash drives. You can also share your own datasets based on the FAF server configuration.
The FAF has the following features:
- Users can browse the datasets provided by all file server applications in the system, rather than those provided by a single application.
- The file access client can operate files through the file selector application, without obtaining the permission to use the FAF.
- Multiple temporarily mounted devices, such as external storage cards and distributed devices, can be accessed at the same time.
## Data Models
Data models in the FAF are transferred through URI, FileInfo, and RootInfo. For details, see [fileExtension](../reference/apis/js-apis-fileExtensionInfo.md). Applications on the file access server can use the **FileAccessExtensionAbility** APIs to securely share their data.
**Figure 2** Data flow of the public file access framework
![](figures/faf-data-flow.png)
NOTE
- In the FAF, the file access client does not directly interact with the file access server. The client only needs to have the permission to start the file selector application.
- The file selector application provides a standard document access UI for users, even if the underlying file access servers differ greatly.
...@@ -12,9 +12,9 @@ To ensure the application running efficiency, most **MediaLibrary** API calls ar ...@@ -12,9 +12,9 @@ To ensure the application running efficiency, most **MediaLibrary** API calls ar
You can obtain images and videos in an album in either of the following ways: You can obtain images and videos in an album in either of the following ways:
- Call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1) with an album specified to obtain the media assets. For details, see [Querying Media Assets with the Specified Album Name](medialibrary-resource-guidelines#querying-media-assets-with-the-specified-album-name). - Call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1) with an album specified to obtain the media assets. For details, see [Querying Media Assets with the Specified Album Name](medialibrary-resource-guidelines.md#querying-media-assets-with-the-specified-album-name).
- Call [Album.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-3) to obtain an **Album** instance, so as to obtain the media assets in it. For details, see [Obtaining Images and Videos in an Album](medialibrary-resource-guidelines#obtaining-images-and-videos-in-an-album). - Call [Album.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-3) to obtain an **Album** instance, so as to obtain the media assets in it. For details, see [Obtaining Images and Videos in an Album](medialibrary-resource-guidelines.md#obtaining-images-and-videos-in-an-album).
## Creating an Album ## Creating an Album
......
...@@ -69,7 +69,7 @@ You can call [fileio.open](../reference/apis/js-apis-fileio.md#fileioopen7) to o ...@@ -69,7 +69,7 @@ You can call [fileio.open](../reference/apis/js-apis-fileio.md#fileioopen7) to o
**How to Develop** **How to Develop**
1. Call [Context.getFilesDir](../reference/apis/js-apis-Context.md#contextgetfilesdir) to obtain the directory of the application sandbox. 1. Call [Context.getFilesDir](../reference/apis/js-apis-inner-app-context.md#contextgetfilesdir) to obtain the directory of the application sandbox.
2. Call **MediaLibrary.getFileAssets** and **FetchFileResult.getFirstObject** to obtain the first file in the result set of the public directory. 2. Call **MediaLibrary.getFileAssets** and **FetchFileResult.getFirstObject** to obtain the first file in the result set of the public directory.
3. Call **fileio.open** to open the file in the sandbox. 3. Call **fileio.open** to open the file in the sandbox.
4. Call **fileAsset.open** to open the file in the public directory. 4. Call **fileAsset.open** to open the file in the public directory.
......
# Internationalization # Internationalization
- [Internationalization Overview](international-overview.md) - [Internationalization Overview](international-overview.md)
- [Internationalization Development (intl)](intl-guidelines.md) - [intl Development](intl-guidelines.md)
- [Internationalization Development (i18n)](i18n-guidelines.md) - [i18n Development](i18n-guidelines.md)
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
## Introduction ## Introduction
You can use audio playback APIs to convert audio data into audible analog signals and play the signals using output devices. You can also manage playback tasks. For example, you can start, suspend, stop playback, release resources, set the volume, seek to a playback position, and obtain track information. You can use audio playback APIs to convert audio data into audible analog signals and play the signals using output devices. You can also manage playback tasks. For example, you can control the playback and volume, obtain track information, and release resources.
## Working Principles ## Working Principles
The following figures show the audio playback status changes and the interaction with external modules for audio playback. The following figures show the audio playback state transition and the interaction with external modules for audio playback.
**Figure 1** Audio playback state transition **Figure 1** Audio playback state transition
...@@ -28,7 +28,7 @@ For details about the APIs, see [AudioPlayer in the Media API](../reference/apis ...@@ -28,7 +28,7 @@ For details about the APIs, see [AudioPlayer in the Media API](../reference/apis
> **NOTE** > **NOTE**
> >
> The method for obtaining the path in the FA model is different from that in the stage model. **pathDir** used in the sample code below is an example. You need to obtain the path based on project requirements. For details about how to obtain the path, see [Application Sandbox Path Guidelines](../reference/apis/js-apis-fileio.md#guidelines). > The method for obtaining the path in the FA model is different from that in the stage model. For details about how to obtain the path, see [Application Sandbox Path Guidelines](../reference/apis/js-apis-fileio.md#guidelines).
### Full-Process Scenario ### Full-Process Scenario
...@@ -109,7 +109,7 @@ async function audioPlayerDemo() { ...@@ -109,7 +109,7 @@ async function audioPlayerDemo() {
setCallBack(audioPlayer); // Set the event callbacks. setCallBack(audioPlayer); // Set the event callbacks.
// 2. Set the URI of the audio file. // 2. Set the URI of the audio file.
let fdPath = 'fd://' let fdPath = 'fd://'
let pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements. let pathDir = "/data/storage/el2/base/haps/entry/files" // The path used here is an example. Obtain the path based on project requirements.
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command. // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3' let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
...@@ -151,7 +151,7 @@ export class AudioDemo { ...@@ -151,7 +151,7 @@ export class AudioDemo {
let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance. let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance.
this.setCallBack(audioPlayer); // Set the event callbacks. this.setCallBack(audioPlayer); // Set the event callbacks.
let fdPath = 'fd://' let fdPath = 'fd://'
let pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements. let pathDir = "/data/storage/el2/base/haps/entry/files" // The path used here is an example. Obtain the path based on project requirements.
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command. // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3' let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
...@@ -199,7 +199,7 @@ export class AudioDemo { ...@@ -199,7 +199,7 @@ export class AudioDemo {
async nextMusic(audioPlayer) { async nextMusic(audioPlayer) {
this.isNextMusic = true; this.isNextMusic = true;
let nextFdPath = 'fd://' let nextFdPath = 'fd://'
let pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements. let pathDir = "/data/storage/el2/base/haps/entry/files" // The path used here is an example. Obtain the path based on project requirements.
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\02.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command. // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\02.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let nextpath = pathDir + '/02.mp3' let nextpath = pathDir + '/02.mp3'
await fileIO.open(nextpath).then((fdNumber) => { await fileIO.open(nextpath).then((fdNumber) => {
...@@ -217,7 +217,7 @@ export class AudioDemo { ...@@ -217,7 +217,7 @@ export class AudioDemo {
let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance. let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance.
this.setCallBack(audioPlayer); // Set the event callbacks. this.setCallBack(audioPlayer); // Set the event callbacks.
let fdPath = 'fd://' let fdPath = 'fd://'
let pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements. let pathDir = "/data/storage/el2/base/haps/entry/files" // The path used here is an example. Obtain the path based on project requirements.
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command. // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3' let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
...@@ -256,7 +256,7 @@ export class AudioDemo { ...@@ -256,7 +256,7 @@ export class AudioDemo {
let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance. let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance.
this.setCallBack(audioPlayer); // Set the event callbacks. this.setCallBack(audioPlayer); // Set the event callbacks.
let fdPath = 'fd://' let fdPath = 'fd://'
let pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements. let pathDir = "/data/storage/el2/base/haps/entry/files" // The path used here is an example. Obtain the path based on project requirements.
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command. // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3' let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
......
...@@ -3,27 +3,30 @@ ...@@ -3,27 +3,30 @@
## Introduction ## Introduction
**AudioRenderer** provides APIs for rendering audio files and controlling playback. It also supports audio interruption. You can use the APIs provided by **AudioRenderer** to play audio files in output devices and manage playback tasks. **AudioRenderer** provides APIs for rendering audio files and controlling playback. It also supports audio interruption. You can use the APIs provided by **AudioRenderer** to play audio files in output devices and manage playback tasks.
Before calling the APIs, be familiar with the following terms: Before calling the APIs, be familiar with the following terms:
- **Audio interruption**: When an audio stream with a higher priority needs to be played, the audio renderer interrupts the stream with a lower priority. For example, if a call comes in when the user is listening to music, the music playback, which is the lower priority stream, is paused. - **Audio interruption**: When an audio stream with a higher priority needs to be played, the audio renderer interrupts the stream with a lower priority. For example, if a call comes in when the user is listening to music, the music playback, which is the lower priority stream, is paused.
- **Status check**: During application development, you are advised to use **on('stateChange')** to subscribe to state changes of the **AudioRenderer** instance. This is because some operations can be performed only when the audio renderer is in a given state. If the application performs an operation when the audio renderer is not in the given state, the system may throw an exception or generate other undefined behavior. - **Status check**: During application development, you are advised to use **on('stateChange')** to subscribe to state changes of the **AudioRenderer** instance. This is because some operations can be performed only when the audio renderer is in a given state. If the application performs an operation when the audio renderer is not in the given state, the system may throw an exception or generate other undefined behavior.
- **Asynchronous operation**: To prevent the UI thread from being blocked, most **AudioRenderer** calls are asynchronous. Each API provides the callback and promise functions. The following examples use the promise functions. For more information, see [AudioRenderer in Audio Management](../reference/apis/js-apis-audio.md#audiorenderer8). - **Asynchronous operation**: To prevent the UI thread from being blocked, most **AudioRenderer** calls are asynchronous. Each API provides the callback and promise functions. The following examples use the promise functions. For more information, see [AudioRenderer in Audio Management](../reference/apis/js-apis-audio.md#audiorenderer8).
- **Audio interruption mode**: OpenHarmony provides two audio interruption modes: **shared mode** and **independent mode**. In shared mode, all **AudioRenderer** instances created by the same application share one focus object, and there is no focus transfer inside the application. Therefore, no callback will be triggered. In independent mode, each **AudioRenderer** instance has an independent focus object, and focus preemption occurs. Focus preemption triggers focus transfer, and the **AudioRenderer** instance that originally has the focus receives a notification through the callback. By default, the shared mode is used. You can call **setInterruptMode()** to set the independent mode. - **Audio interruption mode**: OpenHarmony provides two audio interruption modes: **shared mode** and **independent mode**. In shared mode, all **AudioRenderer** instances created by the same application share one focus object, and there is no focus transfer inside the application. Therefore, no callback will be triggered. In independent mode, each **AudioRenderer** instance has an independent focus object, and focus transfer is triggered by focus preemption. When focus transfer occurs, the **AudioRenderer** instance that is having the focus receives a notification through the callback. By default, the shared mode is used. You can call **setInterruptMode()** to switch to the independent mode.
## Working Principles ## Working Principles
The following figure shows the audio renderer state transitions. The following figure shows the audio renderer state transitions.
Figure 1 Audio renderer state transitions **Figure 1** Audio renderer state transitions
![audio-renderer-state](figures/audio-renderer-state.png) ![audio-renderer-state](figures/audio-renderer-state.png)
- **PREPARED**: The audio renderer enters this state by calling **create()**. - **PREPARED**: The audio renderer enters this state by calling **create()**.
- **RUNNING**: The audio renderer enters this state by calling **start()** when it is in the **PREPARED** state or by calling **start()** when it is in the **STOPPED** state. - **RUNNING**: The audio renderer enters this state by calling **start()** when it is in the **PREPARED** state or by calling **start()** when it is in the **STOPPED** state.
- **PAUSED**: The audio renderer in the **RUNNING** state can call **pause()** to pause the audio playback. After the audio playback is paused, it can call **start()** to resume the playback.
- **STOPPED**: The audio renderer in the **PAUSED** or **RUNNING** state can call **stop()** to stop the playback. - **PAUSED**: The audio renderer enters this state by calling **pause()** when it is in the **RUNNING** state. When the audio playback is paused, it can call **start()** to resume the playback.
- **RELEASED**: The audio renderer in the **PREPARED**, **PAUSED**, or **STOPPED** state can use **release()** to release all occupied hardware and software resources. It will not transit to any other state after it enters the **RELEASED** state.
- **STOPPED**: The audio renderer enters this state by calling **stop()** when it is in the **PAUSED** or **RUNNING** state.
- **RELEASED**: The audio renderer enters this state by calling **release()** when it is in the **PREPARED**, **PAUSED**, or **STOPPED** state. In this state, the audio renderer releases all occupied hardware and software resources and will not transit to any other state.
## How to Develop ## How to Develop
...@@ -62,7 +65,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -62,7 +65,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
```js ```js
async function startRenderer() { async function startRenderer() {
let state = audioRenderer.state; let state = audioRenderer.state;
// The audio renderer should be in the STATE_PREPARED, STATE_PAUSED, or STATE_STOPPED state after being started. // The audio renderer should be in the STATE_PREPARED, STATE_PAUSED, or STATE_STOPPED state when start() is called.
if (state != audio.AudioState.STATE_PREPARED && state != audio.AudioState.STATE_PAUSED && if (state != audio.AudioState.STATE_PREPARED && state != audio.AudioState.STATE_PAUSED &&
state != audio.AudioState.STATE_STOPPED) { state != audio.AudioState.STATE_STOPPED) {
console.info('Renderer is not in a correct state to start'); console.info('Renderer is not in a correct state to start');
...@@ -258,8 +261,8 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -258,8 +261,8 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
let interruptMode : audio.InterruptMode = audio.InterruptMode.SHARE_MODE; let interruptMode : audio.InterruptMode = audio.InterruptMode.SHARE_MODE;
await audioRenderer.setInterruptMode(interruptMode); await audioRenderer.setInterruptMode(interruptMode);
// Set the volume of the stream to 10. // Set the volume of the stream to 0.5.
let volume : number = 10; let volume : number = 0.5;
await audioRenderer.setVolume(volume); await audioRenderer.setVolume(volume);
``` ```
...@@ -303,7 +306,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -303,7 +306,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
case audio.InterruptHint.INTERRUPT_HINT_RESUME: case audio.InterruptHint.INTERRUPT_HINT_RESUME:
startRenderer(); startRenderer();
break; break;
// Notify the application that the audio stream is interrupted. The application determines whether to continue. (In this example, the application pauses the rendering.) // Notify the application that the audio stream is interrupted. The application then determines whether to continue. (In this example, the application pauses the rendering.)
case audio.InterruptHint.INTERRUPT_HINT_PAUSE: case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
isPlay = false; isPlay = false;
pauseRenderer(); pauseRenderer();
...@@ -312,7 +315,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -312,7 +315,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
} }
}); });
audioRenderer.off('audioInterrupt'); // Unsubscribe from the audio interruption event. This event will no longer be received. audioRenderer.off('audioInterrupt'); // Unsubscribe from the audio interruption event. This event will no longer be listened for.
``` ```
10. (Optional) Use **on('markReach')** to subscribe to the mark reached event, and use **off('markReach')** to unsubscribe from the event. 10. (Optional) Use **on('markReach')** to subscribe to the mark reached event, and use **off('markReach')** to unsubscribe from the event.
...@@ -358,7 +361,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -358,7 +361,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
```js ```js
try { try {
audioRenderer.on('invalidInput', () => { // The string does not match. audioRenderer.on('invalidInput', () => { // The string is invalid.
}) })
} catch (err) { } catch (err) {
console.info(`Call on function error, ${err}`); // The application throws exception 401. console.info(`Call on function error, ${err}`); // The application throws exception 401.
...@@ -373,7 +376,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -373,7 +376,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
14. (Optional) Refer to the complete example of **on('audioInterrupt')**. 14. (Optional) Refer to the complete example of **on('audioInterrupt')**.
Create **AudioRender1** and **AudioRender2** in an application, configure the independent interruption mode, and call **on('audioInterrupt')** to subscribe to audio interruption events. At the beginning, **AudioRender1** has the focus. When **AudioRender2** attempts to obtain the focus, **AudioRenderer1** receives a focus transfer notification and the related log information is printed. If the shared mode is used, the log information will not be printed during application running. Create **AudioRender1** and **AudioRender2** in an application, configure the independent interruption mode, and call **on('audioInterrupt')** to subscribe to audio interruption events. At the beginning, **AudioRender1** has the focus. When **AudioRender2** attempts to obtain the focus, **AudioRender1** receives a focus transfer notification and the related log information is printed. If the shared mode is used, the log information will not be printed during application running.
```js ```js
async runningAudioRender1(){ async runningAudioRender1(){
...@@ -429,7 +432,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -429,7 +432,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
let rlen = 0; let rlen = 0;
rlen += bufferSize; rlen += bufferSize;
// 1.7 Render the original audio data in the buffer by using audioRenderer. // 1.7 Render the original audio data in the buffer by using audioRender.
let id = setInterval(async () => { let id = setInterval(async () => {
if (audioRenderer1.state == audio.AudioState.STATE_RELEASED) { // The rendering stops if the audio renderer is in the STATE_RELEASED state. if (audioRenderer1.state == audio.AudioState.STATE_RELEASED) { // The rendering stops if the audio renderer is in the STATE_RELEASED state.
ss1.closeSync(); ss1.closeSync();
...@@ -505,7 +508,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th ...@@ -505,7 +508,7 @@ Set parameters of the **AudioRenderer** instance in **audioRendererOptions**. Th
let rlen = 0; let rlen = 0;
rlen += bufferSize; rlen += bufferSize;
// 2.7 Render the original audio data in the buffer by using audioRenderer. // 2.7 Render the original audio data in the buffer by using audioRender.
let id = setInterval(async () => { let id = setInterval(async () => {
if (audioRenderer2.state == audio.AudioState.STATE_RELEASED) { // The rendering stops if the audio renderer is in the STATE_RELEASED state. if (audioRenderer2.state == audio.AudioState.STATE_RELEASED) { // The rendering stops if the audio renderer is in the STATE_RELEASED state.
ss2.closeSync(); ss2.closeSync();
......
...@@ -81,6 +81,9 @@ for (let index = 0; index < cameraArray.length; index++) { ...@@ -81,6 +81,9 @@ for (let index = 0; index < cameraArray.length; index++) {
// Create a camera input stream. // Create a camera input stream.
let cameraInput = await cameraManager.createCameraInput(cameraArray[0]) let cameraInput = await cameraManager.createCameraInput(cameraArray[0])
// Open camera
await cameraInput.open();
// Obtain the output stream capabilities supported by the camera. // Obtain the output stream capabilities supported by the camera.
let cameraOutputCap = await cameraManager.getSupportedOutputCapability(cameraArray[0]); let cameraOutputCap = await cameraManager.getSupportedOutputCapability(cameraArray[0]);
if (!cameraOutputCap) { if (!cameraOutputCap) {
......
...@@ -19,18 +19,25 @@ const color = new ArrayBuffer(96); // Create a buffer to store image pixel data. ...@@ -19,18 +19,25 @@ const color = new ArrayBuffer(96); // Create a buffer to store image pixel data.
let opts = { alphaType: 0, editable: true, pixelFormat: 4, scaleMode: 1, size: { height: 2, width: 3 } } // Image pixel data. let opts = { alphaType: 0, editable: true, pixelFormat: 4, scaleMode: 1, size: { height: 2, width: 3 } } // Image pixel data.
// Create a PixelMap object. // Create a PixelMap object.
const color = new ArrayBuffer(96); image.createPixelMap(color, opts, (err, pixelmap) => {
let opts = { alphaType: 0, editable: true, pixelFormat: 4, scaleMode: 1, size: { height: 2, width: 3 } }
image.createPixelMap(color, opts, pixelmap => {
console.log('Succeeded in creating pixelmap.'); console.log('Succeeded in creating pixelmap.');
}) // Failed to create the PixelMap object.
if (err) {
console.info('create pixelmap failed, err' + err);
return
}
// Read pixels. // Read pixels.
pixelmap.readPixels(area,(data) => { const area = {
if(data !== null) { pixels: new ArrayBuffer(8),
var bufferArr = new Uint8Array(area.pixels); offset: 0,
var res = true; stride: 8,
for (var i = 0; i < bufferArr.length; i++) { region: { size: { height: 1, width: 2 }, x: 0, y: 0 }
}
pixelmap.readPixels(area,() => {
let bufferArr = new Uint8Array(area.pixels);
let res = true;
for (let i = 0; i < bufferArr.length; i++) {
console.info(' buffer ' + bufferArr[i]); console.info(' buffer ' + bufferArr[i]);
if(res) { if(res) {
if(bufferArr[i] == 0) { if(bufferArr[i] == 0) {
...@@ -40,87 +47,93 @@ pixelmap.readPixels(area,(data) => { ...@@ -40,87 +47,93 @@ pixelmap.readPixels(area,(data) => {
} }
} }
} }
} })
})
// Store pixels. // Store pixels.
const readBuffer = new ArrayBuffer(96); const readBuffer = new ArrayBuffer(96);
pixelmap.readPixelsToBuffer(readBuffer,() => { pixelmap.readPixelsToBuffer(readBuffer,() => {
var bufferArr = new Uint8Array(readBuffer); let bufferArr = new Uint8Array(readBuffer);
var res = true; let res = true;
for (var i = 0; i < bufferArr.length; i++) { for (let i = 0; i < bufferArr.length; i++) {
if(res) {
if (bufferArr[i] !== 0) {
res = false;
console.log('readPixelsToBuffer end.');
break;
}
}
}
})
// Write pixels.
pixelmap.writePixels(area,() => {
const readArea = { pixels: new ArrayBuffer(20), offset: 0, stride: 8, region: { size: { height: 1, width: 2 }, x: 0, y: 0 }}
pixelmap.readPixels(readArea,() => {
var readArr = new Uint8Array(readArea.pixels);
var res = true;
for (var i = 0; i < readArr.length; i++) {
if(res) { if(res) {
if (readArr[i] !== 0) { if (bufferArr[i] !== 0) {
res = false; res = false;
console.log('readPixels end.please check buffer'); console.log('readPixelsToBuffer end.');
break; break;
} }
} }
} }
}) })
})
// Write pixels.
// Write pixels to the buffer. pixelmap.writePixels(area,() => {
pixelmap.writeBufferToPixels(writeColor).then(() => { const readArea = { pixels: new ArrayBuffer(20), offset: 0, stride: 8, region: { size: { height: 1, width: 2 }, x: 0, y: 0 }}
const readBuffer = new ArrayBuffer(96); pixelmap.readPixels(readArea,() => {
pixelmap.readPixelsToBuffer(readBuffer).then (() => { let readArr = new Uint8Array(readArea.pixels);
var bufferArr = new Uint8Array(readBuffer); let res = true;
var res = true; for (let i = 0; i < readArr.length; i++) {
for (var i = 0; i < bufferArr.length; i++) { if(res) {
if(res) { if (readArr[i] !== 0) {
if (bufferArr[i] !== i) { res = false;
res = false; console.log('readPixels end.please check buffer');
console.log('readPixels end.please check buffer'); break;
break; }
} }
} }
} })
}) })
})
// Obtain image information. const writeColor = new ArrayBuffer(96); // Pixel data of the image.
pixelmap.getImageInfo( imageInfo => { // Write pixels to the buffer.
if (imageInfo !== null) { pixelmap.writeBufferToPixels(writeColor).then(() => {
console.log('Succeeded in getting imageInfo'); const readBuffer = new ArrayBuffer(96);
} pixelmap.readPixelsToBuffer(readBuffer).then (() => {
}) let bufferArr = new Uint8Array(readBuffer);
let res = true;
for (let i = 0; i < bufferArr.length; i++) {
if(res) {
if (bufferArr[i] !== i) {
res = false;
console.log('readPixels end.please check buffer');
break;
}
}
}
})
})
// Obtain image information.
pixelmap.getImageInfo((err, imageInfo) => {
// Failed to obtain the image information.
if (err || imageInfo == null) {
console.info('getImageInfo failed, err' + err);
return
}
if (imageInfo !== null) {
console.log('Succeeded in getting imageInfo');
}
})
// Release the PixelMap object. // Release the PixelMap object.
pixelmap.release(()=>{ pixelmap.release(()=>{
console.log('Succeeded in releasing pixelmap'); console.log('Succeeded in releasing pixelmap');
})
}) })
// Create an image source (uri). // Create an image source (uri).
let path = '/data/local/tmp/test.jpg'; let path = '/data/local/tmp/test.jpg';
const imageSourceApi = image.createImageSource(path); const imageSourceApi1 = image.createImageSource(path);
// Create an image source (fd). // Create an image source (fd).
let fd = 29; let fd = 29;
const imageSourceApi = image.createImageSource(fd); const imageSourceApi2 = image.createImageSource(fd);
// Create an image source (data). // Create an image source (data).
const data = new ArrayBuffer(96); const data = new ArrayBuffer(96);
const imageSourceApi = image.createImageSource(data); const imageSourceApi3 = image.createImageSource(data);
// Release the image source. // Release the image source.
imageSourceApi.release(() => { imageSourceApi3.release(() => {
console.log('Succeeded in releasing imagesource'); console.log('Succeeded in releasing imagesource');
}) })
...@@ -128,7 +141,11 @@ imageSourceApi.release(() => { ...@@ -128,7 +141,11 @@ imageSourceApi.release(() => {
const imagePackerApi = image.createImagePacker(); const imagePackerApi = image.createImagePacker();
const imageSourceApi = image.createImageSource(0); const imageSourceApi = image.createImageSource(0);
let packOpts = { format:"image/jpeg", quality:98 }; let packOpts = { format:"image/jpeg", quality:98 };
imagePackerApi.packing(imageSourceApi, packOpts, data => { imagePackerApi.packing(imageSourceApi, packOpts, (err, data) => {
if (err) {
console.info('packing from imagePackerApi failed, err' + err);
return
}
console.log('Succeeded in packing'); console.log('Succeeded in packing');
}) })
...@@ -156,41 +173,34 @@ let decodingOptions = { ...@@ -156,41 +173,34 @@ let decodingOptions = {
}; };
// Create a pixel map in callback mode. // Create a pixel map in callback mode.
imageSourceApi.createPixelMap(decodingOptions, pixelmap => { imageSourceApi.createPixelMap(decodingOptions, (err, pixelmap) => {
// Failed to create the PixelMap object.
if (err) {
console.info('create pixelmap failed, err' + err);
return
}
console.log('Succeeded in creating pixelmap.'); console.log('Succeeded in creating pixelmap.');
}) })
// Create a pixel map in promise mode. // Create a pixel map in promise mode.
imageSourceApi.createPixelMap().then(pixelmap => { imageSourceApi.createPixelMap().then(pixelmap => {
console.log('Succeeded in creating pixelmap.'); console.log('Succeeded in creating pixelmap.');
})
// Capture error information when an exception occurs during function invoking. // Obtain the number of bytes in each line of pixels.
catch(error => { let num = pixelmap.getBytesNumberPerRow();
console.log('Failed in creating pixelmap.' + error);
})
// Obtain the number of bytes in each line of pixels.
pixelmap.getBytesNumberPerRow( num => {
console.log('Succeeded in getting BytesNumber PerRow.');
})
// Obtain the total number of pixel bytes.
pixelmap.getPixelBytesNumber(num => {
console.log('Succeeded in getting PixelBytesNumber.');
})
// Obtain the pixel map information. // Obtain the total number of pixel bytes.
pixelmap.getImageInfo( imageInfo => {}) let pixelSize = pixelmap.getPixelBytesNumber();
// Release the PixelMap object. // Obtain the pixel map information.
pixelmap.release(()=>{ pixelmap.getImageInfo().then( imageInfo => {});
console.log('Succeeded in releasing pixelmap');
})
// Capture release failure information. // Release the PixelMap object.
catch(error => { pixelmap.release(()=>{
console.log('Failed in releasing pixelmap.' + error); console.log('Succeeded in releasing pixelmap');
})
}).catch(error => {
console.log('Failed in creating pixelmap.' + error);
}) })
``` ```
...@@ -216,7 +226,7 @@ if (imagePackerApi == null) { ...@@ -216,7 +226,7 @@ if (imagePackerApi == null) {
} }
// Set encoding parameters if the image packer is successfully created. // Set encoding parameters if the image packer is successfully created.
let packOpts = { format:["image/jpeg"], // The supported encoding format is jpg. let packOpts = { format:"image/jpeg", // The supported encoding format is jpg.
quality:98 } // Image quality, which ranges from 0 to 100. quality:98 } // Image quality, which ranges from 0 to 100.
// Encode the image. // Encode the image.
...@@ -229,12 +239,13 @@ imagePackerApi.packing(imageSourceApi, packOpts) ...@@ -229,12 +239,13 @@ imagePackerApi.packing(imageSourceApi, packOpts)
imagePackerApi.release(); imagePackerApi.release();
// Obtain the image source information. // Obtain the image source information.
imageSourceApi.getImageInfo(imageInfo => { imageSourceApi.getImageInfo((err, imageInfo) => {
console.log('Succeeded in getting imageInfo'); console.log('Succeeded in getting imageInfo');
}) })
const array = new ArrayBuffer(100); // Incremental data.
// Update incremental data. // Update incremental data.
imageSourceIncrementalSApi.updateData(array, false, 0, 10,(error, data)=> {}) imageSourceApi.updateData(array, false, 0, 10,(error, data)=> {})
``` ```
...@@ -246,11 +257,17 @@ Example scenario: The camera functions as the client to transmit image data to t ...@@ -246,11 +257,17 @@ Example scenario: The camera functions as the client to transmit image data to t
public async init(surfaceId: any) { public async init(surfaceId: any) {
// (Server code) Create an ImageReceiver object. // (Server code) Create an ImageReceiver object.
var receiver = image.createImageReceiver(8 * 1024, 8, image.ImageFormat.JPEG, 1); let receiver = image.createImageReceiver(8 * 1024, 8, image.ImageFormat.JPEG, 1);
// Obtain the surface ID. // Obtain the surface ID.
var surfaceId = await receiver.getReceivingSurfaceId(); receiver.getReceivingSurfaceId((err, surfaceId) => {
// Failed to obtain the surface ID.
if (err) {
console.info('getReceivingSurfaceId failed, err' + err);
return
}
console.info("receiver getReceivingSurfaceId success");
});
// Register a surface listener, which is triggered after the buffer of the surface is ready. // Register a surface listener, which is triggered after the buffer of the surface is ready.
receiver.on('imageArrival', () => { receiver.on('imageArrival', () => {
// Obtain the latest buffer of the surface. // Obtain the latest buffer of the surface.
......
...@@ -5,3 +5,4 @@ ...@@ -5,3 +5,4 @@
- [Raw File Development](rawfile-guidelines.md) - [Raw File Development](rawfile-guidelines.md)
- [Native Window Development](native-window-guidelines.md) - [Native Window Development](native-window-guidelines.md)
- [Using MindSpore Lite for Model Inference](mindspore-lite-guidelines.md) - [Using MindSpore Lite for Model Inference](mindspore-lite-guidelines.md)
- [Connecting the Neural Network Runtime to an AI Inference Framework](neural-network-runtime-guidelines.md)
...@@ -24,7 +24,7 @@ APIs involved in MindSpore Lite model inference are categorized into context API ...@@ -24,7 +24,7 @@ APIs involved in MindSpore Lite model inference are categorized into context API
| ------------------ | ----------------- | | ------------------ | ----------------- |
|OH_AI_ContextHandle OH_AI_ContextCreate()|Creates a context object.| |OH_AI_ContextHandle OH_AI_ContextCreate()|Creates a context object.|
|void OH_AI_ContextSetThreadNum(OH_AI_ContextHandle context, int32_t thread_num)|Sets the number of runtime threads.| |void OH_AI_ContextSetThreadNum(OH_AI_ContextHandle context, int32_t thread_num)|Sets the number of runtime threads.|
| void OH_AI_ContextSetThreadAffinityMode(OH_AI_ContextHandle context, int mode)|Sets the affinity mode for binding runtime threads to CPU cores, which are categorized into little cores and big cores depending on the CPU frequency.| | void OH_AI_ContextSetThreadAffinityMode(OH_AI_ContextHandle context, int mode)|Sets the affinity mode for binding runtime threads to CPU cores, which are classified into large, medium, and small cores based on the CPU frequency. You only need to bind the large or medium cores, but not small cores.|
|OH_AI_DeviceInfoHandle OH_AI_DeviceInfoCreate(OH_AI_DeviceType device_type)|Creates a runtime device information object.| |OH_AI_DeviceInfoHandle OH_AI_DeviceInfoCreate(OH_AI_DeviceType device_type)|Creates a runtime device information object.|
|void OH_AI_ContextDestroy(OH_AI_ContextHandle *context)|Destroys a context object.| |void OH_AI_ContextDestroy(OH_AI_ContextHandle *context)|Destroys a context object.|
|void OH_AI_DeviceInfoSetEnableFP16(OH_AI_DeviceInfoHandle device_info, bool is_fp16)|Sets whether to enable float16 inference. This function is available only for CPU and GPU devices.| |void OH_AI_DeviceInfoSetEnableFP16(OH_AI_DeviceInfoHandle device_info, bool is_fp16)|Sets whether to enable float16 inference. This function is available only for CPU and GPU devices.|
......
# Using Native APIs in Application Projects # Using Native APIs in Application Projects
OpenHarmony applications use JavaScript (JS) when calling native APIs. The native APIs (NAPIs) provided by the [ace_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository are used to implement interaction with JS. Currently, the **ace_napi** repository supports some third-party **Node.js** interfaces. The names of the NAPIs are the same as those in the third-party **Node.js**. For details about the interfaces supported, see `libnapi.ndk.json` in this repository. OpenHarmony applications use JavaScript (JS) when calling native APIs. The native APIs (NAPIs) provided by the [ace_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository are used to implement interaction with JS. The names of the NAPIs are the same as those in the third-party **Node.js**. For details about the interfaces supported, see **libnapi.ndk.json** in the ace_napi repository.
## How to Develop ## How to Develop
The IDE has a default project that uses NAPIs. You can choose `File` > `New` > `Create Project` to create a `Native C++` project. The **cpp** directory is generated in the **main** directory. You can use the NAPIs provided by the **ace_napi** repository for development. The DevEco Studio has a default project that uses NAPIs.
You can `import` the native .so that contains the JS processing logic. For example, `import hello from 'libhello.so'` to use the **libhello.so** capability. Then, the JS object created using the NAPI can be passed to the `hello` object of the application to call the native capability. You can choose **File** > **New** > **Create Project** to create a **Native C++** project. The **cpp** directory is generated in the **main** directory. You can use the NAPIs provided by the **ace_napi** repository for development.
You can import the native .so that contains the JS processing logic. For example, **import hello from 'libhello.so'** to use the **libhello.so** capability. Then, the JS object created using the NAPI can be passed to the **hello** object of the application to call the native capability.
## Development Guidelines ## Development Guidelines
...@@ -17,7 +19,7 @@ You can `import` the native .so that contains the JS processing logic. For examp ...@@ -17,7 +19,7 @@ You can `import` the native .so that contains the JS processing logic. For examp
### .so Naming Rules ### .so Naming Rules
Each module has a .so file. For example, if the module name is `hello`, name the .so file `libhello.so`. The `nm_modname` field in `napi_module` must be `hello`, which is the same as the module name. The sample code for importing the .so file is `import hello from 'libhello.so'`. Each module has a .so file. For example, if the module name is **hello**, name the .so file **libhello.so**. The **nm_modname** field in **napi_module** must be **hello**, which is the same as the module name. The sample code for importing the .so file is **import hello from 'libhello.so'**.
### JS Objects and Threads ### JS Objects and Threads
...@@ -28,7 +30,7 @@ The Ark engine prevents NAPIs from being called to operate JS objects in non-JS ...@@ -28,7 +30,7 @@ The Ark engine prevents NAPIs from being called to operate JS objects in non-JS
### Importing Header Files ### Importing Header Files
Before using NAPI objects and methods, include **napi/native_api.h**. Otherwise, when only the third-party library header file is included, an error will be reporting, indicating that the interface cannot be found. Before using NAPI objects and methods, include **napi/native_api.h**. Otherwise, if only the third-party library header file is included, an error will be reporting, indicating that the interface cannot be found.
### napi_create_async_work ### napi_create_async_work
...@@ -50,11 +52,11 @@ napi_status napi_create_async_work(napi_env env, ...@@ -50,11 +52,11 @@ napi_status napi_create_async_work(napi_env env,
## Example 1: Encapsulating Synchronous and Asynchronous APIs for the Storage Module ## Encapsulating Synchronous and Asynchronous APIs for the Storage Module
### Overview ### Overview
This example shows how to encapsulate the synchronous and asynchronous APIs of the storage module. The storage module implements the functions of storing, obtaining, deleting, and clearing data. This example shows how to encapsulate the synchronous and asynchronous APIs of the **Storage** module. The **Storage** module implements the functions of storing, obtaining, deleting, and clearing data.
### API Declaration ### API Declaration
...@@ -79,11 +81,11 @@ export default storage; ...@@ -79,11 +81,11 @@ export default storage;
### Implementation ### Implementation
You can obtain the complete code from `sample/native_module_storage/` in the [OpenHarmony/arkui_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository. You can obtain the complete code from sample/native_module_storage/ in the [OpenHarmony/arkui_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository.
#### Registering the Module **1. Register the module.**
Register four synchronous APIs (`getSync`, `setSync`, `removeSync`, and`clearSync`) and four asynchronous APIs (`get`, `set`, `remove`, and `clear`). Register four synchronous APIs (**getSync**, **setSync**, **removeSync**, and **clearSync**) and four asynchronous APIs (**get**, **set**, **remove**, and **clear**).
```c++ ```c++
/*********************************************** /***********************************************
...@@ -122,9 +124,9 @@ extern "C" __attribute__((constructor)) void StorageRegister() ...@@ -122,9 +124,9 @@ extern "C" __attribute__((constructor)) void StorageRegister()
} }
``` ```
#### Implementing getSync **2. Implement getSync.**
The **getSync** function registered for the storage module is **JSStorageGetSync**. Obtain data from `gKeyValueStorage`, create a string object, and return it. The **getSync** function registered for the **Storage** module is **JSStorageGetSync**. Obtain data from **gKeyValueStorage**, create a string object, and return the object created.
```c ```c
static napi_value JSStorageGetSync(napi_env env, napi_callback_info info) static napi_value JSStorageGetSync(napi_env env, napi_callback_info info)
...@@ -168,9 +170,9 @@ static napi_value JSStorageGetSync(napi_env env, napi_callback_info info) ...@@ -168,9 +170,9 @@ static napi_value JSStorageGetSync(napi_env env, napi_callback_info info)
} }
``` ```
#### Implementing get **3. Implement get().**
The `get` function registered for the storage module is `JSStorageGet`. The **get** function registered for the **Storage** module is **JSStorageGet**.
```c ```c
static napi_value JSStorageGet(napi_env env, napi_callback_info info) static napi_value JSStorageGet(napi_env env, napi_callback_info info)
...@@ -268,7 +270,7 @@ static napi_value JSStorageGet(napi_env env, napi_callback_info info) ...@@ -268,7 +270,7 @@ static napi_value JSStorageGet(napi_env env, napi_callback_info info)
} }
``` ```
### JS Sample Code **JS Sample Code**
```js ```js
import storage from 'libstorage.so'; import storage from 'libstorage.so';
...@@ -292,11 +294,11 @@ export default { ...@@ -292,11 +294,11 @@ export default {
## Example 2: Binding Native and JS Objects for the NetServer Module ## Binding Native and JS Objects for the NetServer Module
### Overview ### Overview
This example shows how to implement the `on/off/once` method and bind C++ and JS objects using the **wrap** API. The NetServer module implements the network service. This example shows how to implement the **on**, **off**, and **once** methods and bind C++ and JS objects using **wrap()**. The **NetServer** module implements the network service.
### API Declaration ### API Declaration
...@@ -312,9 +314,9 @@ export class NetServer { ...@@ -312,9 +314,9 @@ export class NetServer {
### Implementation ### Implementation
You can obtain the complete code from `sample/native_module_netserver/` in the [OpenHarmony/arkui_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository. You can obtain the complete code from **sample/native_module_netserver/** in the [OpenHarmony/arkui_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository.
#### Registering the Module **1. Register the module.**
```c ```c
static napi_value NetServer::Export(napi_env env, napi_value exports) static napi_value NetServer::Export(napi_env env, napi_value exports)
...@@ -338,7 +340,7 @@ static napi_value NetServer::Export(napi_env env, napi_value exports) ...@@ -338,7 +340,7 @@ static napi_value NetServer::Export(napi_env env, napi_value exports)
} }
``` ```
#### Binding C++ and JS Objects in a Constructor **2. Bind C++ and JS objects in a constructor.**
```c ```c
napi_value NetServer::JS_Constructor(napi_env env, napi_callback_info cbinfo) napi_value NetServer::JS_Constructor(napi_env env, napi_callback_info cbinfo)
...@@ -365,7 +367,7 @@ napi_value NetServer::JS_Constructor(napi_env env, napi_callback_info cbinfo) ...@@ -365,7 +367,7 @@ napi_value NetServer::JS_Constructor(napi_env env, napi_callback_info cbinfo)
} }
``` ```
#### Obtaining the C++ Object from the JS Object **3. Obtain a C++ object from a JS object.**
```c ```c
napi_value NetServer::JS_Start(napi_env env, napi_callback_info cbinfo) napi_value NetServer::JS_Start(napi_env env, napi_callback_info cbinfo)
...@@ -398,7 +400,7 @@ napi_value NetServer::JS_Start(napi_env env, napi_callback_info cbinfo) ...@@ -398,7 +400,7 @@ napi_value NetServer::JS_Start(napi_env env, napi_callback_info cbinfo)
} }
``` ```
After `netServer->Start` is executed, call back the `start` event registered by `on`. After **netServer->Start** is executed, call back the **start** event registered by **on()**.
```c ```c
int NetServer::Start(int port) int NetServer::Start(int port)
...@@ -435,7 +437,7 @@ int NetServer::Start(int port) ...@@ -435,7 +437,7 @@ int NetServer::Start(int port)
} }
``` ```
#### Registering Events (on) **4. Call on() to register an event observer.**
```c ```c
napi_value NetServer::JS_On(napi_env env, napi_callback_info cbinfo) napi_value NetServer::JS_On(napi_env env, napi_callback_info cbinfo)
...@@ -475,7 +477,7 @@ napi_value NetServer::JS_On(napi_env env, napi_callback_info cbinfo) ...@@ -475,7 +477,7 @@ napi_value NetServer::JS_On(napi_env env, napi_callback_info cbinfo)
} }
``` ```
### JS Sample Code **JS Sample Code**
```javascript ```javascript
import { NetServer } from 'libnetserver.so'; import { NetServer } from 'libnetserver.so';
...@@ -491,7 +493,7 @@ export default { ...@@ -491,7 +493,7 @@ export default {
## Example 3: Calling Back a JS API in a Non-JS Thread ## Calling Back a JS API in a Non-JS Thread
### Overview ### Overview
...@@ -499,11 +501,11 @@ This example describes how to invoke a JS callback in a non-JS thread. For examp ...@@ -499,11 +501,11 @@ This example describes how to invoke a JS callback in a non-JS thread. For examp
### Implementation ### Implementation
You can obtain the complete code from `sample/native_module_callback/` in the [OpenHarmony/arkui_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository. You can obtain the complete code from **sample/native_module_callback/** in the [OpenHarmony/arkui_napi](https://gitee.com/openharmony/arkui_napi/tree/master) repository.
#### Registering the Module **1. Register the module.**
Register the `test` API to pass in a parameter. Register the **test** API to pass in a parameter.
```c++ ```c++
/*********************************************** /***********************************************
...@@ -536,7 +538,7 @@ extern "C" __attribute__((constructor)) void CallbackTestRegister() ...@@ -536,7 +538,7 @@ extern "C" __attribute__((constructor)) void CallbackTestRegister()
} }
``` ```
#### Obtaining the Loop in env and Throwing the Task to the JS Thread **2. Obtain the loop in env and throw the task to a JS thread.**
```c++ ```c++
#include <thread> #include <thread>
...@@ -627,7 +629,7 @@ static napi_value JSTest(napi_env env, napi_callback_info info) ...@@ -627,7 +629,7 @@ static napi_value JSTest(napi_env env, napi_callback_info info)
} }
``` ```
### JS Sample Code **JS Sample Code**
```js ```js
import callback from 'libcallback.so'; import callback from 'libcallback.so';
......
# Common Event and Notification # Notification
- [Notification Overview](notification-overview.md)
- [Notification Subscription (Open Only to System Applications)](notification-subscription.md)
- [Enabling Notification](notification-enable.md)
- Publishing a Notification
- [Publishing a Basic Notification](text-notification.md)
- [Publishing a Progress Notification](progress-bar-notification.md)
- [Adding a WantAgent Object to a Notification](notification-with-wantagent.md)
- [Common Event and Notification Overview](notification-brief.md)
- [Common Event Development](common-event.md)
- [Notification Development](notification-guidelines.md)
- Agent-Powered Scheduled Reminder
- [Agent-Powered Scheduled Reminder Overview](background-agent-scheduled-reminder-overview.md)
- [Agent-Powered Scheduled Reminder Development](background-agent-scheduled-reminder-guide.md)
- [Debugging Assistant Usage](assistant-guidelines.md)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册