OpenHarmony(数据)通信协议、数据存储—protobuf
介绍
ProtoBuf(protocol buffers) 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。,是一种灵活,高效,自动化机制的结构数据序列化方法比XML更小,更快,更为简单。
本项目主要是OpenHarmony系统下以protobuf.js 5.0.3为主要依赖开发,主要接口针对OpenHarmony系统进行合理的适配研发。
下载安装
1.安装
ohpm install @ohos/protobufjs
2.在需要使用的页面导入protobuf
import protobuf from '@ohos/protobufjs'
使用说明
protobuf支持的输入格式
1.proto格式字符串
const protoStr = 'syntax = "proto3"; package com.user;message UserLoginResponse{string sessionId = 1;string userPrivilege = 2;bool isTokenType = 3;string formatTimestamp = 4;}';
2.proto文件映射的json字符串
const protoJson = '{"package": "com.user","messages": [{"name": "UserLoginResponse","fields": [{"rule": "optional","type": "string","name": "sessionId","id": 1},{"rule": "optional","type": "string","name": "userPrivilege","id": 2},{"rule": "optional","type": "bool","name": "isTokenType","id": 3},{"rule": "optional","type": "string","name": "formatTimestamp","id": 4}]}]
}'
3.proto文件
在resource->rawfile文件夹下按照 .proto文件格式定义消息体结构,如:userproto.proto文件。
syntax = "proto3";package com.user;
message UserLoginResponse{string sessionId = 1;string userPrivilege = 2;bool isTokenType = 3;string formatTimestamp = 4;
}
4.json文件
在resource->rawfile文件夹下存放proto文件映射的json文件,参照第二点。
对象编解码
1.在resource->rawfile文件夹下按照 .proto文件格式定义消息体结构,如:userproto.proto文件。
syntax = "proto3";package com.user;
message UserLoginResponse{string sessionId = 1;string userPrivilege = 2;bool isTokenType = 3;string formatTimestamp = 4;
}
2.读取.proto 文件
let builder = await Protobuf.loadProtoFile("userproto.proto", null, null, getContext(this).resourceManager)
3.对象编码
// 构建消息体
var UserLoginResponse = builder.build("com.user.UserLoginResponse");
let userLoginData = {sessionId: "testAsynchronouslyLoadProtoFile",userPrivilege: "John123",isTokenType: false,formatTimestamp: "12342222"};// 对象编码的两种方式
// 方式一:通过消息体静态编码方法进行编码
var arrayBuffer = UserLoginResponse.encode(userLoginData).toArrayBuffer();// 方式二:通过消息体实例进行编解码
var msg = new UserLoginResponse(userLoginData);
var arrayBuffer = msg.toArrayBuffer();
4.对象解码
let decode = UserLoginResponse.decode(arrayBuffer)
主要接口示例:
1.proto字符串编解码
Button("proto字符串编解码").width('80%').type(ButtonType.Capsule).backgroundColor('#0D9FFB').onClick(async () => {try {// 1.创建protbuf.Builder对象:用于构造协议消息体。var builder = protobuf.newBuilder();// 2.加载proto字符串:解析协议消息体定义。var root = await protobuf.loadProto(protoStr, builder, "user.proto");// 3.构建协议消息体。var UserLoginResponse = root.build("com.user.UserLoginResponse");// 设置编解码数据const userLogin = {sessionId: "loadProto",userPrivilege: "John123",isTokenType: false,formatTimestamp: "12342222"};// 4.实例Message消息体:通过builder找到协议名后会产生Message,创建符合协议结构的数据对象,作为参数实例协议消息体。var msg = new UserLoginResponse(userLogin);// 5.消息体编码:可用于通信传递或存储var arrayBuffer = msg.toArrayBuffer();// 6.消息体解码:得到原始消息体内容var decodeMsg = UserLoginResponse.decode(arrayBuffer);} catch (error) {console.info('protobuf single file catch error: ' + error)}});
2.json字符串编解码
Button("json字符串编解码").width('80%').type(ButtonType.Capsule).backgroundColor('#0D9FFB').onClick(async () => {try {// 1.创建protbuf.Builder对象:用于构造协议消息体。var builder = protobuf.newBuilder();// 2.加载json字符串:解析协议消息体定义。var root = await protobuf.loadProto(protoJson, builder, "user.json");// 3.构建协议消息体。var UserLoginResponse = root.build("com.user.UserLoginResponse");// 设置编解码数据const userLogin = {sessionId: "loadJson",userPrivilege: "John123",isTokenType: false,formatTimestamp: "12342222"};// 4.实例Message消息体:通过builder找到协议名后会产生Message,创建符合协议结构的数据对象,作为参数实例协议消息体。var msg = new UserLoginResponse(userLogin);// 5.消息体编码:可用于通信传递或存储var arrayBuffer = msg.toArrayBuffer();// 6.消息体解码:得到原始消息体内容var decodeMsg = UserLoginResponse.decode(arrayBuffer);} catch (error) {console.info('protobuf single file catch error: ' + error)}});
3.同步方式进行proto文件编解码
Button("同步方式进行proto文件编解码").width('80%').type(ButtonType.Capsule).backgroundColor('#0D9FFB').onClick(async () => {try {// 读取文件需要借助全球化资源子系统中的ResourceManager来进行,支持多种方式获取// 方式一: 通过GlobalContext对象保存ability上下文中的resourceManager对象// 方式二: 通过getContext()方式获取// 在pages页面中获取: getContext(this).resourceManagerlet context: Context = GlobalContext.getContext().getObject("context") as Context;var builder = await protobuf.loadProtoFile('userproto.proto', null, null, context.resourceManager);if (!builder) {console.error('protobuf codec: builder is null|undefined.');return;}var UserLoginResponse = builder.build("com.user.UserLoginResponse");var msg = new UserLoginResponse(this.userLogin);var arrayBuffer = msg.toArrayBuffer();console.log("protobuf arrayBuffer:" + new Uint8Array(arrayBuffer));var decodeMsg = UserLoginResponse.decode(arrayBuffer);console.log("protobuf decode:" + JSON.stringify(decodeMsg));} catch (error) {console.info('protobuf single file catch error: ' + error)}});
4.异步方式进行proto文件编解码
Button("异步方式进行proto文件编解码").width('80%').type(ButtonType.Capsule).backgroundColor('#0D9FFB').onClick(() => {try {let context: Context = GlobalContext.getContext().getObject("context") as Context;protobuf.loadProtoFile('userproto.proto', (error, builder) => {if (error) {console.error('protobuf codec catch error: ' + error);return;}if (!builder) {console.error('protobuf codec: builder is null|undefined.');return;}var UserLoginResponse = builder.build("com.user.UserLoginResponse");var msg = new UserLoginResponse(this.userLogin);console.log("protobuf msg:" var arrayBuffer = msg.toArrayBuffer();console.log("protobuf arrayBuffer:" + new Uint8Array(arrayBuffer));this.bufferData = Array.prototype.toString.call(new Uint8Array(arrayBuvar decodeMsg = UserLoginResponse.decode(arrayBuffer);console.log("protobuf decode:" + JSON.stringify(decodeMsg));this.decodeData = JSON.stringify(decodeMsg);}, null, context.resourceManager);} catch (error) {console.info('protobuf single file catch error: ' + error)}});
接口说明
loadProto
static loadProto(proto:string,builder?:ProtoBuf.Builder|string|{root: string, file: string},filename?:string|{root: string, file: string}) :ProtoBuf.Builder;
加载proto格式字符串,进行内容解析,并返回协议消息体构建器。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
proto | string | 是 | proto格式的字符串。 |
builder | Builder |string | {root: string, file: string} | 否 | 指定已有的协议消息体构建器,如果未指定将重新创建一个。 |
filename | string | {root: string, file: string} | 否 | 如果知道对应的文件名称,必须为导入文件指定。 |
返回值:
类型 | 说明 |
---|---|
Builder | 协议消息体构建器。 |
protoFromString
static protoFromString(proto:string,builder?:ProtoBuf.Builder|string|{root: string, file: string},filename?:string|{root: string, file: string}) :ProtoBuf.Builder;
loadProto方法的别名,加载proto格式字符串,进行内容解析,并返回协议消息体构建器。
参数
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
proto | string | 是 | proto格式的字符串。 |
builder | Builder |string | {root: string, file: string} | 否 | 指定已有的协议消息体构建器,如果未指定将重新创建一个。 |
filename | string | {root: string, file: string} | 否 | 如果知道对应的文件名称,必须为导入文件指定。 |
返回值:
类型 | 说明 |
---|---|
Builder | 协议消息体构建器。 |
loadProtoFile
static loadProtoFile(filename:string|{root: string, file: string}, callback?=(error?:Error,builder:Protobuf.Builder)=>void,builder?:Protobuf.Builder,resourceManager: @ohos.resourceManager.ResourceManager):ProtoBuf.Builder|undefined;
加载proto文件,进行内容解析,并返回协议消息体构建器。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
filename | string | {root: string, file: string} | 是 | 原始文件的路径或指定’file’的对象,并为所有导入的文件覆盖’根’路径。 |
callback | function | 否 | 成功时将接收’ null '作为第一个参数,并将Builder作为第二个参数,否则将Error作为第一个参数。如果省略,文件将被同步读取。 |
builder | Builder | 否 | 指定已有的协议消息体构建器,如果未指定将重新创建一个。 |
resourceManager | @ohos.resourceManager.ResourceManager | 是 | 访问应用资源的能力。 |
表1 callback的参数说明
参数名 | 类型 | 说明 |
---|---|---|
error | Error | 如果解析成功,此参数返回’null’,如果失败,返回对应Error。 |
builder | Builder | 协议消息体构建器。 |
返回值:
类型 | 说明 |
---|---|
Builder | null | 协议消息体构建器。 |
protoFromFile
static protoFromFile(filename:string|{root: string, file: string}, callback?=(error?:Error,builder:Protobuf.Builder)=>void,builder?:Protobuf.Builder,resourceManager: @ohos.resourceManager.ResourceManager):ProtoBuf.Builder|undefined;
loadProtoFile方法别名,加载proto文件,进行内容解析,并返回协议消息体构建器。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
filename | string | {root: string, file: string} | 是 | 原始文件的路径或指定’file’的对象,并为所有导入的文件覆盖’根’路径。 |
callback | function | 否 | 成功时将接收’ null '作为第一个参数,并将Builder作为第二个参数,否则将Error作为第一个参数。如果省略,文件将被同步读取。 |
builder | Builder | 否 | 指定已有的协议消息体构建器,如果未指定将重新创建一个。 |
resourceManager | @ohos.resourceManager.ResourceManager | 是 | 访问应用资源的能力。 |
表1 callback的参数说明
参数名 | 类型 | 说明 |
---|---|---|
error | Error | 如果解析成功,此参数返回’null’,如果失败,返回对应Error。 |
builder | Builder | 协议消息体构建器。 |
返回值:
类型 | 说明 |
---|---|
Builder | undefined | 协议消息体构建器。 |
loadJson
static loadJson(json:string|any, builder?:Protobuf.Builder|string| {root: string, file: string}, filename?: string| {root: string, file: string} ): ProtoBuf.Builder;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
json | string | any | 是 | proto格式的json字符串或者proto文件对应的json对象。 |
builder | Builder |string | {root: string, file: string} | 否 | 指定已有的协议消息体构建器,如果未指定将重新创建一个。 |
filename | string | {root: string, file: string} | 否 | 如果知道对应的文件名称,必须为导入文件指定。 |
返回值:
类型 | 说明 |
---|---|
Builder | 协议消息体构建器。 |
loadJsonFile
static loadJsonFile(filename:string|{root: string, file: string}, callback?=(error?:Error,builder:Protobuf.Builder)=>void,builder?:Protobuf.Builder,resourceManager: @ohos.resourceManager.ResourceManager):ProtoBuf.Builder|undefined;
加载proto文件,进行内容解析,并返回协议消息体构建器。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
filename | string | {root: string, file: string} | 是 | 原始文件的路径或指定’file’的对象,并为所有导入的文件覆盖’根’路径。 |
callback | function | 否 | 成功时将接收’ null '作为第一个参数,并将Builder作为第二个参数,否则将Error作为第一个参数。如果省略,文件将被同步读取。 |
builder | Builder | 否 | 指定已有的协议消息体构建器,如果未指定将重新创建一个。 |
resourceManager | @ohos.resourceManager.ResourceManager | 是 | 访问应用资源的能力。 |
表1 callback的参数说明
参数名 | 类型 | 说明 |
---|---|---|
error | Error | 如果解析成功,此参数返回’null’,如果失败,返回对应Error。 |
builder | Builder | 协议消息体构建器。 |
返回值:
类型 | 说明 |
---|---|
Builder | undefined | 协议消息体构建器。 |
newBuilder
static newBuilder():Protobuf.Builder;
返回值:
类型 | 说明 |
---|---|
Builder | 协议消息体构建器。 |
Util
以下接口在Util对象内,须通过Protobuf.Util方式调用。
fetch
static fetch(path:string, callback?:(content?:string)=> void):string|undefined.
获取文件内容,需要先设置资源文件读取对象ResourceManager。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
path | string | 是 | 资源文件路径。 |
callback | (content?:string)=> void | 否 | 回调接收资源的内容。如果省略,资源将被同步获取。如果请求失败,内容将为空。 |
返回值:
类型 | 说明 |
---|---|
string | undefined | 资源文件内容。 |
toCamelCase
static toCamelCase(str:string):string;
用于将字符串转换为驼峰格式。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
str | string | 是 | 将字符串转换为驼峰格式。 |
返回值:
类型 | 说明 |
---|---|
string | 驼峰格式字符串。 |
Builder
构建协议消息体的构建器,提供构建协议消息的功能。
isMessage
static isMessage(def:Object):boolean;
用于判断指定对象是否为消息体。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
def | Object | 是 | 判断指定对象是否为消息体。 |
返回值:
类型 | 说明 |
---|---|
boolean | 指示对象是否为消息体。 |
isMessageField
static isMessageField(def:Object):boolean;
用于判断指定对象是否为消息体的字段。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
def | Object | 是 | 判断指定对象是否为消息体的字段。 |
返回值:
类型 | 说明 |
---|---|
boolean | 指示对象是否为消息体的字段。 |
isEnum
static isEnum(def:Object):boolean;
用于判断指定对象是否为枚举对象。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
def | Object | 是 | 判断指定对象是否为枚举对象。 |
返回值:
类型 | 说明 |
---|---|
boolean | 指示对象是否为枚举对象。 |
build
build(path?: string | string[]) : Protobuf.Builder.Message | Object;
用于构建协议,解析所有定义,返回构建的协议消息包。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
path | string | string[] | 否 | 协议内包完整路径。 |
返回值:
类型 | 说明 |
---|---|
Protobuf.Builder.Message | Object | 协议消息包。 |
lookup
lookup(path?: string, excludeNonNamespace?: boolean) : ProtoBuf.Reflect.T;
用于构建协议消息包。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
path | string | 否 | 协议内包完整路径。 |
excludeNonNamespace | boolean | 否 | 排除非命名空间类型,如fields,默认为false。 |
返回值:
类型 | 说明 |
---|---|
ProtoBuf.Reflect.T | 反射的描述。 |
Message
提供协议消息体的编解码方法。
constructor
new Message(values:Object);
构建消息体实例。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
values | Object | 是 | 符合协议消息体结构的数据对象。 |
encode
static encode(data: Object, buffer?: ByteBuffer | boolean, noVerify?: boolean):ByteBuffer;
将协议消息体编码为ByteBuffer格式。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
data | string | 是 | 消息体对应的数据。 |
buffer | boolean | 否 | 指定编解码结果的ByteBuffer对象,如果未指定,将创建一个新的。 |
noVerify | boolean | 否 | 是否不验证字段值,默认为false。 |
返回值:
类型 | 说明 |
---|---|
ByteBuffer | 协议消息体数据编码后的ByteBuffer数据。 |
encode
encode(buffer?: ByteBuffer| boolean, noVerify?: boolean): ByteBuffer;
将消息编码为ByteBuffer格式数据。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
buffer | string | 是 | 指定编解码结果的ByteBuffer对象,如果未指定,将创建一个新的。 |
noVerify | boolean | 否 | 是否不验证字段值,默认为false。 |
返回值:
类型 | 说明 |
---|---|
ByteBuffer | 协议消息体数据编码后的ByteBuffer数据。 |
encodeAB
encodeAB():ArrayBuffer;
将消息编码为ArrayBuffer格式。
返回值:
类型 | 说明 |
---|---|
ArrayBuffer | 协议消息体数据编码后的ArrayBuffer数据。 |
toArrayBuffer
toArrayBuffer():ArrayBuffer;
encodeAB方法的别名,用于将消息编码为ArrayBuffer格式。
返回值:
类型 | 说明 |
---|---|
ArrayBuffer | 协议消息体数据编码后的ArrayBuffer数据。 |
calculate
calculate(): Number;
计算消息体长度。
返回值:
类型 | 说明 |
---|---|
Number | 协议消息体的长度。 |
encodeDelimited
encodeDelimited(buffer?: ByteBuffer| boolean, noVerify?: boolean): ByteBuffer;
将消息编码为ByteBuffer格式数据。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
buffer | string | 是 | 指定编解码结果的ByteBuffer对象,如果未指定,将创建一个新的。 |
noVerify | boolean | 否 | 是否不验证字段值,默认为false。 |
返回值:
类型 | 说明 |
---|---|
ByteBuffer | 协议消息体数据编码后的ByteBuffer数据。 |
encode64
encode64(): string;
将消息编码为base64编码的字符串。
返回值:
类型 | 说明 |
---|---|
string | 将消息编码为base64编码的字符串。 |
toBase64
toBase64(): string;
encode64方法的别名,将消息编码为base64编码的字符串。
返回值:
类型 | 说明 |
---|---|
string | 将消息编码为base64编码的字符串。 |
encodeHex
encodeHex(): string;
将消息编码为十六进制编码的字符串。
返回值:
类型 | 说明 |
---|---|
string | 将消息编码为十六进制编码的字符串。 |
toHex
toHex(): string;
encodeHex方法的别名,将消息编码为十六进制编码的字符串。
返回值:
类型 | 说明 |
---|---|
string | 将消息编码为十六机制编码的字符串。 |
encodeJson
encodeJson(): string;
将消息编码为Json字符串。
返回值:
类型 | 说明 |
---|---|
string | 将消息编码为Json字符串。 |
toRaw
toRaw(binaryAsBase64?:boolean, longsAsStrings:boolean):Object;
返回消息的原始负载。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
databinaryAsBase64 | boolean | 否 | 指示是否包含二进制数据作为base64字符串而不是缓冲区,默认为false。 |
longsAsStrings | boolean | 是 | 指示是否将long编码为字符串。 |
返回值:
类型 | 说明 |
---|---|
Object | 返回消息的原始负载。 |
decode
static decode(data: ByteBuffer|ArrayBuffer|Buffer|string, length?: Number| string, enc?: string):Protobuf.Builder.Message;
从指定的缓冲区或字符串解码消息。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
data | ByteBuffer | ArrayBuffer | Buffer | string | 是 | 要解码的数据。 |
length | Number | string | 否 | 消息体长度,默认解码所有数据。 |
enc | string | 否 | 如果缓冲区是字符串,将进行编码,支持hex,base64,utf8(不推荐),默认为base64 |
返回值:
类型 | 说明 |
---|---|
Protobuf.Builder.Message | 从指定的缓冲区或字符串解码消息。 |
decode64
static decode64(str:string):Protobuf.Builder.Message;
从指定的base64编码字符串解码消息。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
str | string | 是 | 要解码的base64编码字符串数据。 |
返回值:
类型 | 说明 |
---|---|
Protobuf.Builder.Message | 从指定的base64编码字符串解码消息。 |
decodeHex
static decodeHex(str:string):Protobuf.Builder.Message;
从指定的十六进制编码字符串解码消息。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
str | string | 是 | 要解码的十六进制编码字符串数据。 |
返回值:
类型 | 说明 |
---|---|
Protobuf.Builder.Message | 从指定的十六进制编码字符串解码消息。 |
decodeJson
static decodeJson(str:string):Protobuf.Builder.Message;
从JSON字符串解码消息。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
str | string | 是 | 从JSON字符串解码消息。 |
返回值:
类型 | 说明 |
---|---|
Protobuf.Builder.Message | 从JSON字符串解码消息。 |
decodeDelimited
static decodeDelimited(buffer: ByteBuffer | ArrayBuffer | Buffer | string, enc?: string):Protobuf.Builder.Message;
从指定的缓冲区或字符串解码以长度分隔的varint32消息。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
buffer | ByteBuffer | ArrayBuffer | Buffer | string | 是 | 指定的缓冲区或字符串。 |
enc | string | 否 | 如果缓冲区是字符串,将进行编码,支持hex,base64,utf8(不推荐),默认为base64。 |
返回值:
类型 | 说明 |
---|---|
Protobuf.Builder.Message | 从指定的缓冲区或字符串解码以长度分隔的varint32消息。 |
约束与限制
在下述版本验证通过:
- DevEco Studio: 4.0 (4.0.3.512), SDK: API10 (4.0.10.9)
- DevEco Studio: 4.0 Release(4.0.3.413), SDK: API10 (4.0.10.3)
目录结构
|---- protobuf
| |---- AppScrope # 示例代码文件夹
| |---- entry # 示例代码文件夹
| |---- protobufjs # protobufjs库文件夹
| |---- src/main # 模块代码
| |---- ets/ # 模块代码
| |---- dist # 打包文件
| |---- index.ets # 入口文件
| |---- .ohpmignore # ohpm发布的忽略文件
| |---- *.json5 # 配置文件
| |---- README.md # 安装使用方法
| |---- README.OpenSource # 开源说明
| |---- CHANGELOG.md # 更新日志
经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?
为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:gitee.com/MNxiaona/733GH
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH
OpenHarmony 开发环境搭建
《OpenHarmony源码解析》
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
- 系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……
OpenHarmony 设备开发学习手册
写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:
gitee.com/MNxiaona/733GH
相关文章:

OpenHarmony(数据)通信协议、数据存储—protobuf
介绍 ProtoBuf(protocol buffers) 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。,是一种灵活,高效,自动化机制的结构数据序列化方法比XML更小,更快,更为简单。 本项…...

vue3 依赖注入 vueRouter vuex
目录 01 依赖注入 02 组合式API里面的vueRouter 03 组合式API中的vuex的使用 01 依赖注入 使用场景: 有一个父组件,里头有子组件,有孙组件,有很多后代组件,共享父组件数据。 1.组先组件给后代组件传参 组先组件: 从…...

在Windows上用Visual Studio编译OpenCV
在Windows上编译开源项目,有时候让人痛不欲生,有时候却出奇地顺利。OpenCV属于后者。本文记录这次愉快的过程。 注:OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它提供了大…...

详解2024年最值得推荐的5款CRM软件:如何选择适合企业需求的CRM系统?
在文章开始之前,我们前来了解下:什么是CRM系统? CRM系统,即客户关系管理系统,顾名思义,它是企业用来管理和维护与客户之间关系的重要工具。通过CRM系统,企业能够全面了解客户需求,优…...

2024靠谱的网站建设公司推荐
在现在的互联网社会,一个企业的网站往往是潜在客户对该品牌的第一印象来源。也正因如此,选择一个靠谱的网站建设公司对于确保企业在线形象和功能性至关重要,作为建站行业从业人员,我分享几个选择网站建设公司时应考虑的几个关键因…...

第一天:Java基础与环境搭建
第一天:Java基础与环境搭建 1. 理解Java基本概念 了解Java语言的历史:Java是一种广泛使用的编程语言,由Sun Microsystems(现被Oracle收购)于1995年首次发布。认识Java的特性:包括面向对象、平台无关性&am…...

动画魔法秀:JavaScript前端动画实战指南
标题:动画魔法秀:JavaScript前端动画实战指南 在现代Web开发中,动画不仅能够提升用户体验,还能使网页更加生动有趣。JavaScript作为实现前端动画的重要工具之一,提供了多种方式来创建平滑且吸引人的动画效果。本文将详…...

实训日记day26
NAT服务配置 1.关闭防火墙和selinux [root2 ~]# setenforce 0 [root2 ~]# vim /etc/selinux/config [root2 ~]# systemctl stop firewalld [root2 ~]# systemctl disable firewalld 2.安装nginx (web1和web2) [root2 ~]# yum install -y gcc-c pcre pcr…...

自定义实现一个 Redis 客户端
要自定义实现一个 Redis 客户端并支持密码认证,你可以使用 TCP socket 直接与 Redis 服务器进行通信。下面是如何通过 Java 自定义实现一个简单的 Redis 客户端的详细示例,包括如何发送密码进行认证。 Redis 协议概述 Redis 使用一种称为 RESP…...

sql注入——sqlilabs16-26
文章目录 less-163.注入 less-172.数据库名2.1 floor报错注入数据库名 3.查到数据表3.1floor 报错注入数据表 4.查取列名4.1 floor报错注入 列名 5.查取内容 less-181.添加X-Forwarded-For测试2修改User-Agent测试3.查数据表名4.查数据列5.查取数据 less-192.查数据库3.查数据表…...

数据加载工具pg_bulkload插件的介绍
瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台:Linux x86-64 Red Hat Enterprise Linux 7 版本:12 文档用途 本文档主要介绍pg_bulkload插件的安装与使用。 详细信息 研发公司:NTT OSS Center DBMS Development and Support Team&…...

Windows禁止应用联网
转自两种方法阻止电脑上的软件彻底联网! - 知乎 (zhihu.com) 但为了稳妥,自己还是稍微记录一下 1、创建bat脚本文件 创建文本-将下面的代码填入-保存为.bat文件 Echo Off SetLocal:beginecho: echo ****** 禁止文件夹联网 ****** echo:set /p folder…...

zabbix邮件告警配置
一、报警 触发器的通知信息显示在web管理界面, 运维工程师仍然没办法24小时盯着它。所以我们希望它能自动地 通知工程师们,这就是报警。 zabbix的报警媒介支持email,jabber,sms(短信),微信,电话语音等。 报警过程原理 配置报警信息可以通过邮箱来实现 1、本地邮箱…...

代码随想录算法训练营第 35 天 | LeetCode 416. 分割等和子集
代码随想录算法训练营 Day35 代码随想录算法训练营第 35 天 | LeetCode 416. 分割等和子集 目录 代码随想录算法训练营前言LeetCode416. 分割等和子集 一、LeetCode416. 分割等和子集1.题目链接2.思路3.题解 前言 LeetCode416. 分割等和子集 讲解文档 一、LeetCode416. 分割…...

伪国企是指的什么?
伪国企,也称为虚假国企,主要指的是那些通过不正当手段,如伪造文件、虚假宣传等,误导公众或第三方,使其误认为该企业具有国有企业背景或实际控制权的非国有企业。 一、伪国企类型 具体来说,伪国企可能包括…...

Transformer在量化投资中的应用
开篇 深度学习的发展为我们创建下一代时间序列预测模型提供了强大的工具。深度人工神经网络,作为一种完全以数据驱动的方式学习时间动态的方法,特别适合寻找输入和输出之间复杂的非线性关系的挑战。最初,循环神经网络及其扩展的LSTM网络被设…...

a++ 和 ++a
由于后缀递增/递减运算符需要返回原始值,这可能导致编译器生成额外的代码来保存原始值,因此在某些情况下,前缀递增/递减可能更高效。在不涉及表达式结果的上下文中(例如,在单独的语句中),a和a的…...

Python配置文件格式——INI、JSON、YAML、XML、TOML
文章目录 对比INIJSONYAMLXMLTOML参考文献 对比 格式优点缺点是否支持注释INI简单易懂语言内置支持不支持复杂数据结构✓JSON支持复杂数据结构阅读起来不够直观YAML简洁有序支持复杂数据结构灵活但有歧义不同实现有兼容性问题✓XML支持复杂数据结构和命名空间语法冗长体积较大…...

The First项目报告:Web3人生模拟器,DegenReborn带你重开币圈
2023年6月14日,ReadON APP的首页上,一篇引人注目的文章《黑客马拉松奖:‘Degenreborn’——Meme与GameFi的梦幻交汇》跃然眼前,该文章巧妙融合了NFT、GameFi及Ethereum等热门话题,为读者带来了一场科技与娱乐的盛宴。 …...

燃气经营企业从业人员考试真题及答案
燃气经营企业从业人员考试真题及答案 11.《城镇燃气设计规范》中规定:当穿过卫生间、阁楼或壁柜时,燃气管道应采用()连接(金属软管不得有接头),并应设在钢套管内。 A.法兰 B.软管 C.焊接 D.丝扣 答案:…...

白骑士的Matlab教学进阶篇 2.1 数据可视化
系列目录 上一篇:白骑士的Matlab教学基础篇 1.5 数据输入与输出 数据可视化是MATLAB的一个强大功能,它能够将数据以图形的形式展示出来,便于理解和分析。本文将介绍MATLAB中的基本绘图函数、绘制2D图形、绘制3D图形以及高级图形属性与定制的…...

2024年8月 | 涉及侵权、抄袭洗稿违规行为公示
为护社区良好氛围,守护清朗网络空间,CSDN持续对侵害他人权益、抄袭洗稿违规内容进行治理。 今年7月,CSDN共计删除涉及抄袭洗稿内容xx篇,下架侵权资源xx个,封禁违规账号42个。 部分违规账号公示 账号昵称处置结果封禁创…...

操作系统快速入门(四)
😀前言 本篇博文是关于操作系统的,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力😉&…...

前缀异或优化
前言:这个题目其实就是考察前缀和,正常情况下开二维数组来记录,但是也可以优化成一位的位运算 我们顺便可以学习一下如何进行查询二进制串中1的个数 class Solution { public:vector<bool> canMakePaliQueries(string s, vector<vec…...

AI学习指南深度学习篇-卷积神经网络中的正则化和优化
AI学习指南深度学习篇-卷积神经网络中的正则化和优化 在深度学习领域,卷积神经网络(Convolutional Neural Networks,CNN)是一类非常重要的模型,被广泛应用于图像识别、目标检测等任务中。然而,在训练CNN时…...

AutoGen Studio 本地源码构建
目录 一、环境配置 1.1 创建本地环境 1.2 下载 autogen 源码 1.3 安装依赖 2. 构建 3. 运行 本文主要介绍 AutoGen Studio 本地源码构建过程。 一、环境配置 1.1 创建本地环境 通过 conda 创建一个环境,Python 3.10+,Node.js 14.15.0+。 conda create -n autogen p…...

医疗陪诊系统源码详解:在线问诊APP开发的技术要点
如今,开发一款高效、可靠的在线问诊APP则成为了许多企业的目标。本篇文章,小编将详细解析医疗陪诊系统的源码,并探讨在线问诊APP开发的关键技术要点。 一、医疗陪诊系统的基本功能 在开始开发之前,首先需要明确医疗陪诊系统的基本…...

VSCode编译多个不同文件夹下的C++文件
实际上VSCode编译C文件就是通过向g传递参数实现的,因此即使是不同包下面的cpp文件或者.h文件都是可以通过修改g的编译参数实现,而在VSCode中,task.json文件其实就是在配置g的编译参数,因此我们可以通过修改task.json里面的参数&am…...

【安卓】连接真机和使用通知
文章目录 连接到真机使用通知通知的简单使用通知的详细信息 连接到真机 先用USB线将手机与电脑连接。 打开手机的设置,找到关于手机,点开之后,找到开发者选项界面。或者找到软件版本号,连续点击,系统会提示你点击几次能…...

CSS3下拉菜单实现
导航菜单: <nav class"multi_drop_menu"><!-- 一级开始 --><ul><li><a href"#">Power</a></li><li><a href"#">Money</a></li><li><a href"#"…...