OpenHarmony IDL工具规格及使用说明书(仅对系统应用开放)

news2024/9/25 11:19:15

IDL接口描述语言简介

当客户端和服务器进行IPC通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony IDL(OpenHarmony Interface Definition Language)则是一种定义此类接口的工具。OpenHarmony IDL先把需要传递的对象分解成操作系统能够理解的基本类型,并根据开发者的需要封装跨边界的对象。

图1 IDL接口描述

OpenHarmony IDL接口描述语言主要用于:

  • 声明系统服务对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。

  • 声明Ability对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。

图2 IPC/RPC通信模型

使用OpenHarmony IDL接口描述语言声明接口具有以下优点:

  • OpenHarmony IDL中是以接口的形式定义服务,可以专注于定义而隐藏实现细节。

  • OpenHarmony IDL中定义的接口可以支持跨进程调用或跨设备调用。根据OpenHarmony IDL中的定义生成的信息或代码可以简化跨进程或跨设备调用接口的实现。

IDL接口描述语言构成

数据类型

基础数据类型

IDL支持的基本数据类型及其映射到C++、TS上的数据类型的对应关系如上表所示。

sequenceable数据类型

sequenceable数据类型是指使用“sequenceable”关键字声明的数据,表明该数据类型可以被序列化进行跨进程或跨设备传递。sequenceable在C++与TS中声明方式存在一定差异。

在C++中sequenceable数据类型的声明放在文件的头部,以“sequenceable includedir…namespace.typename”的形式声明。具体而言。声明可以有如下三个形式:

sequenceable includedir..namespace.typename
sequenceable includedir...typename
sequenceable namespace.typename

其中,includedir表示该数据类型头文件所在目录,includedir中以“.”作为分隔符。namespace表示该数据类型所在命名空间,namespace中同样以“.”作为分隔符。typename表示数据类型,数据类型中不能包含非英文字符类型的其他符号。includedir与namespace之间通过“…”分割,如果类型声明的表达式中不包含“…”,除去最后一个typename之外的字符都会被解析为命名空间。例如:

sequenceable a.b..C.D

上述声明在生成的的C++头文件中将被解析为如下代码:

#include  “a/b/d.h”
using C::D;

TS声明放在文件的头部,以 “sequenceable namespace.typename;”的形式声明。具体而言,声明可以有如下形式(idl为对应namespace,MySequenceable为对应typename):

sequenceable idl.MySequenceable

其中,namespace是该类型所属的命名空间,typename是类型名。MySequenceable类型表示可以通过Parcel进行跨进程传递。sequenceable数据类型并不在OpenHarmony IDL文件中定义,而是定义在.ts文件中。因此,OpenHarmony IDL工具将根据声明在生成的.ts代码文件中加入如下语句:

import MySequenceable from "./my_sequenceable"

需要注意的是,IDL并不负责该类型的代码实现,仅仅按照指定的形式引入该头文件或import指定模块,并使用该类型,因此开发者需要自行保证引入目录、命名空间及类型的正确性。

接口类型

接口类型是指OpenHarmony IDL文件中定义的接口。对于当前IDL文件中定义的接口,可以直接使用它作为方法参数类型或返回值类型。而在其它OpenHarmony IDL文件中定义的接口,则需要在文件的头部进行前置声明。

C++中声明的形式与sequenceable类型相似,具体而言可以有如下形式:

interface includedir..namespace.typename

TS中声明的形式,具体而言可以有如下形式:

interface namespace.interfacename

其中,namespace是该接口所属的命名空间,interfacename是接口名。例如:“interface OHOS.IIdlTestObserver;”声明了在其他OpenHarmony IDL文件定义的IIdlTestObserver接口,该接口可以作为当前定义中方法的参数类型或返回值类型使用。OpenHarmony IDL工具将根据该声明在生成的TS代码文件中加入如下语句:

import IIdlTestObserver from "./i_idl_test_observer"
数组类型

数组类型使用“T[]”表示,其中T可以是基本数据类型、sequenceable数据类型、interface类型和数组类型。该类型在C++生成代码中将被生成为std::vector类型。 OpenHarmony IDL数组数据类型与TS数据类型、C++数据类型的对应关系如下表所示:

OpenHarmony IDL数据类型C++数据类型TS数据类型
T[]std::vectorT[]
容器类型

IDL支持两种容器类型,即List和Map。其中List类型容器的用法为List;Map容器的用法为Map<KT,VT>,其中T、KT、VT为基本数据类型、sequenceable类型、interface类型、数组类型或容器类型。

List类型在C++代码中被映射为std::list,Map容器被映射为std::map。

List类型在TS代码中不支持,Map容器被映射为Map。

OpenHarmony IDL容器数据类型与Ts数据类型、C++数据类型的对应关系如下表所示:

OpenHarmony IDL数据类型C++数据类型TS数据类型
Liststd::list不支持
Map<KT,VT>std::mapMap

IDL文件编写规范

一个idl文件只能定义一个interface类型,且该interface名称必须和文件名相同。idl文件的接口定义使用BNF范式描述,其基本定义的形式如下:

[<*interface_attr_declaration*>]interface<*interface_name_with_namespace*>{<*method_declaration*>}

其中,<interface_attr_declaration>表示接口属性声明。当前仅支持“oneway”属性,表示该接口中的接口都是单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。接口名需要包含完整的接口头文件目录及命名空间,且必须包含方法声明,不允许出现空接口。 接口内的方法声明形式为:

[<*method_attr_declaration*>]<*result_type*><*method_declaration*>

其中,<method_attr_declaration>表示接口属性说明。当前仅支持“oneway”属性,表示该方法为单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。<result_type>为返回值类型,<method_declaration>是方法名和各个参数声明。 参数声明的形式为:

[<*formal_param_attr*>]<*type*><*identifier*>

其中<formal_param_attr>的值为“in”,“out”,“inout”,分别表示该参数是输入参数,输出参数或输入输出参数。需要注意的是,如果一个方法被声明为oneway,则该方法不允许有输出类型的参数(及输入输出类型)和返回值。

开发步骤

IDL工具的获取

首先,打开DevEco Studio—>Tools—>SDK Manager,查看OpenHarmony SDK的本地安装路径,此处以DevEco Studio 3.0.0.993版本为例,查看方式如下图所示。

进入对应路径后,查看toolchains->3.x.x.x(对应版本号命名文件夹)下是否存在idl工具的可执行文件。

注意
请保证使用最新版的SDK,版本老旧可能导致部分语句报错。

若不存在,可对应版本前往 docs仓版本目录 下载SDK包,以 3.2Beta3版本 为例,可通过镜像站点获取。

关于如何替换DevEco Studio的SDK包具体操作,参考 full-SDK替换指南 中的替换方法。

得到idl工具的可执行文件后,根据具体场景进行后续开发步骤。

TS开发步骤

创建.idl文件

开发者可以使用TS编程语言构建.idl文件。

例如,此处构建一个名为IIdlTestService.idl的文件,文件内具体内容如下:

  interface OHOS.IIdlTestService {
      int TestIntTransaction([in] int data);
      void TestStringTransaction([in] String data);
      void TestMapTransaction([in] Map<int, int> data);
      int TestArrayTransaction([in] String[] data);
  }

在idl的可执行文件所在文件夹下执行命令 idl -gen-ts -d dir -c dir/IIdlTestService.idl

-d后的dir为目标输出目录,以输出文件夹名为IIdlTestServiceTs为例,在idl可执行文件所在目录下执行idl -gen-ts -d IIdlTestServiceTs -c IIdlTestServiceTs/IIdlTestService.idl,将会在执行环境的dir目录(即IIdlTestServiceTs目录)中生成接口文件、Stub文件、Proxy文件。

注意:生成的接口类文件名称和.idl文件名称保持一致,否则会生成代码时会出现错误。

以名为IIdlTestService.idl的.idl文件、目标输出文件夹为IIdlTestServiceTs为例,其目录结构应类似于:

├── IIdlTestServiceTs  # idl代码输出文件夹
│   ├── i_idl_test_service.ts  # 生成文件
│   ├── idl_test_service_proxy.ts  # 生成文件
│   ├── idl_test_service_stub.ts  # 生成文件
│   └── IIdlTestService.idl  # 构造的.idl文件
└── idl.exe  # idl的可执行文件
服务端公开接口

OpenHarmony IDL工具生成的Stub类是接口类的抽象实现,并且会声明.idl文件中的所有方法。

import {testIntTransactionCallback} from "./i_idl_test_service";
import {testStringTransactionCallback} from "./i_idl_test_service";
import {testMapTransactionCallback} from "./i_idl_test_service";
import {testArrayTransactionCallback} from "./i_idl_test_service";
import IIdlTestService from "./i_idl_test_service";
import rpc from "@ohos.rpc";

export default class IdlTestServiceStub extends rpc.RemoteObject implements IIdlTestService {
    constructor(des: string) {
        super(des);
    }
    
    async onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence,
        option: rpc.MessageOption): Promise<boolean> {
        console.log("onRemoteMessageRequest called, code = " + code);
        if (code == IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION) {
            let _data = data.readInt();
            this.testIntTransaction(_data, (errCode: number, returnValue: number) => {
                reply.writeInt(errCode);
                if (errCode == 0) {
                    reply.writeInt(returnValue);
                }
            });
            return true;
        } else if (code == IdlTestServiceStub.COMMAND_TEST_STRING_TRANSACTION) {
            let _data = data.readString();
            this.testStringTransaction(_data, (errCode: number) => {
                reply.writeInt(errCode);
            });
            return true;
        } else if (code == IdlTestServiceStub.COMMAND_TEST_MAP_TRANSACTION) {
            let _data: Map<number, number> = new Map();
            let _dataSize = data.readInt();
            for (let i = 0; i < _dataSize; ++i) {
                let key = data.readInt();
                let value = data.readInt();
                _data.set(key, value);
            }
            this.testMapTransaction(_data, (errCode: number) => {
                reply.writeInt(errCode);
            });
            return true;
        } else if (code == IdlTestServiceStub.COMMAND_TEST_ARRAY_TRANSACTION) {
            let _data = data.readStringArray();
            this.testArrayTransaction(_data, (errCode: number, returnValue: number) => {
                reply.writeInt(errCode);
                if (errCode == 0) {
                    reply.writeInt(returnValue);
                }
            });
            return true;
        } else {
            console.log("invalid request code" + code);
        }
        return false;
    }
    
    testIntTransaction(data: number, callback: testIntTransactionCallback): void{}
    testStringTransaction(data: string, callback: testStringTransactionCallback): void{}
    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void{}
    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void{}

    static readonly COMMAND_TEST_INT_TRANSACTION = 1;
    static readonly COMMAND_TEST_STRING_TRANSACTION = 2;
    static readonly COMMAND_TEST_MAP_TRANSACTION = 3;
    static readonly COMMAND_TEST_ARRAY_TRANSACTION = 4;
}

开发者需要继承.idl文件中定义的接口类并实现其中的方法。在本示例中,我们继承了IdlTestServiceStub接口类并实现了其中的testIntTransaction、testStringTransaction、testMapTransaction和testArrayTransaction方法。具体的示例代码如下:

import {testIntTransactionCallback} from "./i_idl_test_service"
import {testStringTransactionCallback} from "./i_idl_test_service"
import {testMapTransactionCallback} from "./i_idl_test_service";
import {testArrayTransactionCallback} from "./i_idl_test_service";
import IdlTestServiceStub from "./idl_test_service_stub"


class IdlTestImp extends IdlTestServiceStub {

    testIntTransaction(data: number, callback: testIntTransactionCallback): void
    {
        callback(0, data + 1);
    }
    testStringTransaction(data: string, callback: testStringTransactionCallback): void
    {
        callback(0);
    }
    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void
    {
        callback(0);
    }
    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void
    {
        callback(0, 1);
    }
}

在服务实现接口后,需要向客户端公开该接口,以便客户端进程绑定。如果开发者的服务要公开该接口,请扩展Ability并实现onConnect()从而返回IRemoteObject,以便客户端能与服务进程交互。服务端向客户端公开IRemoteAbility接口的代码示例如下:

import Want from '@ohos.app.ability.Want';
import rpc from "@ohos.rpc";

class ServiceAbility {
  onStart() {
    console.info('ServiceAbility onStart');
  }
  onStop() {
    console.info('ServiceAbility onStop');
  }
  onCommand(want: Want, startId: number) {
    console.info('ServiceAbility onCommand');
  }
  onConnect(want: Want) {
    console.info('ServiceAbility onConnect');
    try {
      console.log('ServiceAbility want:' + typeof(want));
      console.log('ServiceAbility want:' + JSON.stringify(want));
      console.log('ServiceAbility want name:' + want.bundleName)
    } catch(err) {
      console.log('ServiceAbility error:' + err)
    }
    console.info('ServiceAbility onConnect end');
    return new IdlTestImp('connect') as rpc.RemoteObject;
  }
  onDisconnect(want: Want) {
    console.info('ServiceAbility onDisconnect');
    console.info('ServiceAbility want:' + JSON.stringify(want));
  }
}

export default new ServiceAbility()
客户端调用IPC方法

客户端调用connectServiceExtensionAbility()以连接服务时,客户端的onAbilityConnectDone中的onConnect回调会接收服务的onConnect()方法返回的IRemoteObject实例。由于客户端和服务在不同应用内,所以客户端应用的目录内必须包含.idl文件(SDK工具会自动生成Proxy代理类)的副本。客户端的onAbilityConnectDone中的onConnect回调会接收服务的onConnect()方法返回的IRemoteObject实例,使用IRemoteObject创建IdlTestServiceProxy类的实例对象testProxy,然后调用相关IPC方法。示例代码如下:

import common from '@ohos.app.ability.common';
import Want from '@ohos.app.ability.Want';
import IdlTestServiceProxy from './idl_test_service_proxy'

function callbackTestIntTransaction(result: number, ret: number): void {
  if (result == 0 && ret == 124) {
    console.log('case 1 success');
  }
}

function callbackTestStringTransaction(result: number): void {
  if (result == 0) {
    console.log('case 2 success');
  }
}

function callbackTestMapTransaction(result: number): void {
  if (result == 0) {
    console.log('case 3 success');
  }
}

function callbackTestArrayTransaction(result: number, ret: number): void {
  if (result == 0 && ret == 124) {
    console.log('case 4 success');
  }
}

let onAbilityConnectDone: common.ConnectOptions = {
  onConnect: (elementName, proxy) => {
    let testProxy: IdlTestServiceProxy = new IdlTestServiceProxy(proxy);
    let testMap: Map<number, number> = new Map();
    testMap.set(1, 1);
    testMap.set(1, 2);
    testProxy.testIntTransaction(123, callbackTestIntTransaction);
    testProxy.testStringTransaction('hello', callbackTestStringTransaction);
    testProxy.testMapTransaction(testMap, callbackTestMapTransaction);
    testProxy.testArrayTransaction(['1','2'], callbackTestMapTransaction);
  },
  onDisconnect: (elementName) => {
    console.log('onDisconnectService onDisconnect');
  },
  onFailed: (code) => {
    console.log('onDisconnectService onFailed');
  }
};

let context: common.UIAbilityContext = this.context;

function connectAbility(): void {
    let want: Want = {
        bundleName: 'com.example.myapplicationidl',
        abilityName: 'com.example.myapplicationidl.ServiceAbility'
    };
    let connectionId = -1;
    connectionId = context.connectServiceExtensionAbility(want, onAbilityConnectDone);
}
IPC传递sequenceable对象

开发者可以通过 IPC 接口,将某个类从一个进程发送至另一个进程。但是,必须确保 IPC 通道的另一端可使用该类的代码,并且该类必须支持marshalling和unmarshalling方法。系统需要通过marshalling和unmarshalling方法将对象序列化和反序列化成各进程能识别的对象。

如需创建支持sequenceable 类型数据,开发者必须执行以下操作:

  1. 实现marshalling方法,它会获取对象的当前状态并将其序列化后写入Parcel。
  2. 实现unmarshalling方法,它会从Parcel中反序列化出对象。

MySequenceable类的代码示例如下:

import rpc from '@ohos.rpc';
export default class MySequenceable implements rpc.Sequenceable {
    constructor(num: number, str: string) {
        this.num = num;
        this.str = str;
    }
    getNum() : number {
        return this.num;
    }
    getString() : string {
        return this.str;
    }
    marshalling(messageParcel: rpc.MessageParcel) {
        messageParcel.writeInt(this.num);
        messageParcel.writeString(this.str);
        return true;
    }
    unmarshalling(messageParcel: rpc.MessageParcel) {
        this.num = messageParcel.readInt();
        this.str = messageParcel.readString();
        return true;
    }
    private num: number;
    private str: string;
}

C++开发SA步骤(编译期自动生成SA接口模板代码)

创建.idl文件

开发者使用C++编程语言构建.idl文件。

例如,此处构建一个名为IQuickFixManager.idl的文件,文件内具体内容如下:

/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo;
interface OHOS.AAFwk.IQuickFixManager {
    void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
    void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
    void RevokeQuickFix([in] String bundleName);
}
修改BUILD.gn文件
  1. 导入IDL工具模板到当前BUILD.gn文件。
# 此处不需要修改,直接复制到gn中即可
import("//foundation/ability/idl_tool/idl_config.gni")
  1. 调用IDL工具生成C++模板文件。

    示例中的axx_bxx_cxx需要替换为生成的stub和proxy的.cpp名。

idl_interface_sources = [
  # axx_bxx_cxx为需要修改为生成proxy的.cpp名
  "${target_gen_dir}/axx_bxx_cxx_proxy.cpp",                                            
  # axx_bxx_cxx为需要修改为生成stub的.cpp名
  "${target_gen_dir}/axx_bxx_cxx_stub.cpp",
]

# 使用idl_gen_interface生成模板文件、需输入参数名后面的deps中会使用
idl_gen_interface("EEEFFFGGG") {
  # 开发者定义的.idl名,与gn文件在同一路径下
  src_idl = rebase_path("IAxxBxxCxx.idl")
  # proxy和stub模板.cpp文件, 此处不需要修改,直接复制到gn中即可
  dst_file = string_join(",", idl_interface_sources)
  # 开启hitrace,值是hitrace_meter.h文件中定义的uint64_t类型标识,需要填入常量的变量名
  hitrace = "HITRACE_TAG_ABILITY_MANAGER"
  # 开启hilog,Domain ID 使用16进制的整数
  log_domainid = "0xD003900"
  # 开启hilog,字符串类型tag名、一般为子系统名称
  log_tag = "QuickFixManagerService"
}

axx_bxx_cxx_proxy.cpp和axx_bxx_cxx_stub.cpp的命名与.idl文件小写名相同,遇到大写时加"_"。

# 例:.idl文件为IQuickFixManager.idl
axx_bxx_cxx_proxy.cpp为:quick_fix_manager_proxy.cpp
axx_bxx_cxx_stub.cpp为:quick_fix_manager_stub.cpp

如果需要生成的模板文件名第一个字母为I时,需要在interface命名时在前面加一个I。

# 例:生成的模板文件为quick_fix_manager_proxy.cpp时interface的名称应为IQuickFixManager
# .idl文件中的定义
interface OHOS.AAFwk.IQuickFixManager {
    void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
    void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
    void RevokeQuickFix([in] String bundleName);
}

配置hilog,参数log_domainid和log_tag必须成对出现,若只写一个会编译错误。

idl_gen_interface("quickfix_manager_interface") {
  src_idl = rebase_path("IQuickFixManager.idl")
  dst_file = string_join(",", idl_interface_sources)
  hitrace = "HITRACE_TAG_ABILITY_MANAGER"
  log_domainid = "0xD003900"
  log_tag = "QuickFixManagerService"    #只有一个log_tag,编译会错误,同理只有log_domainid,编译也会错误
}
  1. 在BUILD.gn中添加模板文件的头文件路径。

    只需将“${target_gen_dir}”名添加到现有include_dirs中即可,其它不需要更改。

include_dirs = [
  "aaa/bbb/ccc",        # 原有头文件路径
  "${target_gen_dir}",  # 模板头文件路径
]
  1. 在BUILD.gn中添加模板文件.cpp文件路径。

    若sources中有axx_bxx_cxx_proxy.cpp和axx_bxx_cxx_stub.cpp需要删除,并加上sources += filter_include(output_values, [ “*.cpp” ])。

output_values = get_target_outputs(":EEEFFFGGG") # 返回给定目标标签的输出文件列表,替换EEEFFFGGG
sources = [ "axx_bxx_cxx_proxy.cpp" ]  # 需要删除axx_bxx_cxx_proxy.cpp
sources += filter_include(output_values, [ "*.cpp" ]) # filter_include选中符合的列表,直接复制即可
  1. 在BUILD.gn中添加依赖“EEEFFFGGG”。
deps = [
    ":EEEFFFGGG",
  ]

deps添加的依赖名,必须同idl_gen_interface函数参数名相同。

idl_gen_interface("quickfix_manager_interface") {
  src_idl = rebase_path("IQuickFixManager.idl")
  dst_file = string_join(",", idl_interface_sources)
  hitrace = "HITRACE_TAG_ABILITY_MANAGER"
  log_domainid = "0xD003900"
  log_tag = "QuickFixManagerService"
}
deps = [
 "${ability_runtime_innerkits_path}/app_manager:app_manager",
 ":quickfix_manager_interface"]    # idl_gen_interface函数参数名相同
  1. 在BUILD.gn中添加模板文件的外部依赖。

    模板文件的外部依赖需要自己添加到external_deps里。

    若之前已存在,不需要重复添加,若重复添加会导致编译错误。

  external_deps = [
  # 模板文件必须的依赖
  "c_utils:utils",
  # hilog输出必须的依赖
  "hilog:libhilog",
  # hitrace输出必须的依赖
  "hitrace:hitrace_meter",
  # 模板文件必须的依赖
  "ipc:ipc_core",
]
实例

以应用快速修复服务为例:

  1. 创建名为IQuickFixManager.idl文件。

    在创建.idl文件时,interface名称必须和.idl文件名相同,否则会在生成代码时出现错误。

    创建.idl的文件路径与功能代码BUILD.gn的路径相同。

    实例中的位置为:foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/。

/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo;
interface OHOS.AAFwk.IQuickFixManager {
    void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
    void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
    void RevokeQuickFix([in] String bundleName);
}

在创建.idl文件时,需要将返回值为int的函数,修改为void。

# 例 quick_fix_manager_client.h中的函数
    int32_t ApplyQuickFix(const std::vector<std::string> &quickFixFiles);
    int32_t GetApplyedQuickFixInfo(const std::string &bundleName, ApplicationQuickFixInfo &quickFixInfo);
    int32_t RevokeQuickFix(const std::string &bundleName);
# .idl文件中的定义
interface OHOS.AAFwk.QuickFixManager {
    void ApplyQuickFix([in] String[] quickFixFiles);
    void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
    void RevokeQuickFix([in] String bundleName);
}
  1. 修改BUILD.gn文件。
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//build/ohos.gni")
import("//foundation/ability/ability_runtime/ability_runtime.gni")
import("//foundation/ability/idl_tool/idl_config.gni")

idl_interface_sources = [
  "${target_gen_dir}/quick_fix_manager_proxy.cpp",
  "${target_gen_dir}/quick_fix_manager_stub.cpp",
]

idl_gen_interface("quickfix_manager_interface") {
  src_idl = rebase_path("IQuickFixManager.idl")
  dst_file = string_join(",", idl_interface_sources)
  hitrace = "HITRACE_TAG_ABILITY_MANAGER"
  log_domainid = "0xD003900"
  log_tag = "QuickFixManagerService"
}

config("quickfix_config") {
  visibility = [ ":*" ]
  include_dirs = [
    "include",
    "${target_gen_dir}",
  ]
  cflags = []
  if (target_cpu == "arm") {
    cflags += [ "-DBINDER_IPC_32BIT" ]
  }
}

ohos_shared_library("quickfix_manager") {
  configs = [ "${ability_runtime_services_path}/common:common_config" ]
  public_configs = [ ":quickfix_config" ]

  output_values = get_target_outputs(":quickfix_manager_interface")
  sources = [
    "src/quick_fix_error_utils.cpp",
    "src/quick_fix_info.cpp",
    "src/quick_fix_load_callback.cpp",
    "src/quick_fix_manager_client.cpp",
    "src/quick_fix_utils.cpp",
  ]
  sources += filter_include(output_values, [ "*.cpp" ])
  defines = [ "AMS_LOG_TAG = \"QuickFixService\"" ]
  deps = [
    ":quickfix_manager_interface",
    "${ability_runtime_innerkits_path}/app_manager:app_manager",
  ]

  external_deps = [
    "ability_base:want",
    "bundle_framework:appexecfwk_base",
    "bundle_framework:appexecfwk_core",
    "c_utils:utils",
    "hilog:libhilog",
    "hitrace:hitrace_meter",
    "ipc:ipc_single",
    "safwk:system_ability_fwk",
    "samgr:samgr_proxy",
  ]

  innerapi_tags = [ "platformsdk" ]
  subsystem_name = "ability"
  part_name = "ability_runtime"
}
  1. 生成模板文件的路径及目录结构。

    编译以rk3568为例,实例中生成的模板文件路径为:out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/。

    其中foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/为.idl文件所在的相对路径。

    生成文件目录结构为:

|-- out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/
   |-- iquick_fix_manager.h
   |-- quick_fix_manager_stub.h
   |-- quick_fix_manager_stub.cpp
   |-- quick_fix_manager_proxy.h
   |-- quick_fix_manager_proxy.cpp

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1542325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

io流的学习4

字符缓冲流 原理&#xff1a;底层自带了长度为8192的缓冲区提高性能。 import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException;public class BufferedStringdemo01 {public static void main(String…

【旅游景点项目日记 | 第二篇】基于Selenium爬取携程网景点详细数据

文章目录 3.基于Selenium爬取携程网景点详细数据3.1前提环境3.2思路3.3代码详讲3.3.1查询指定城市的所有景点3.3.2获取详细景点的访问路径3.3.3获取景点的详细信息 3.4数据库设计3.5全部代码3.6效果图 3.基于Selenium爬取携程网景点详细数据 3.1前提环境 确保安装python3.x环…

HCIP的学习(4)

GRE和MGRE VPN---虚拟专用网络。指依靠ISP或其他公有网络基础设施上构建的专用的安全数据通信网络。该网络是属于逻辑上的。​ 核心机制—隧道机制&#xff08;封装技术&#xff09; GRE—通用路由封装 ​ 三层隧道技术&#xff0c;并且是属于点到点的隧道。 [r1]interface T…

1+x中级题目练习复盘(九)

注解和注释是两种完全不同的语法&#xff0c;注解可以为程序增加额外的功能&#xff0c;或为程序添加元数据。 函数式接口是指有且只有一个抽象方法的接口&#xff1b; 函数式接口可以使用 FunctionalInterface 进行标注&#xff0c;但不是必须的。除了 “java.util.function…

zabbix安装及使用(错误及解决方案)

安装zabbix 常见错误&#xff1a; Zabbix下载错误 6.0与5.0版本冲突 解决方法 yum -y install zabbix-server-mysql zabbix-web-mysql zabbix-get --skip-broken zabbix6.0-web 自己有数据库&#xff0c;使用以下命令 pid找不到 /var/log/zabbix/zabbix_server.log 错误&a…

[AutoSar]BSW_Com020 Handle_ID,Global_PDU,Local_PDU的联系

目录 关键词平台说明一、概念二、API的使用和形参三、Handle ID 唯一性特例四、PDU和handle ID关联用例 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c; EB芯片厂商TI 英飞凌编程语言C&#xff0c;C编译器HighTec (…

电子电器架构 —— 诊断数据DTC具体故障

电子电器架构 —— 诊断数据DTC具体故障 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣…

Windows 7 静态 IP 地址

Windows 7 静态 IP 地址 References 静态 IP 地址设置为 192.168.1.198 控制面板 -> 查看网络状态和任务 更改适配器设置 网络连接 -> 属性 TCP / IPv4 警告 - 已计划将多个默认网关用于提供单一网络 (例如 intranet 或者 Internet) 的冗余。 6.1. 关闭 redundancy VMw…

【stable diffusion扩散模型】一篇文章讲透

目录 一、引言 二、Stable Diffusion的基本原理 1 扩散模型 2 Stable Diffusion模型架构 3 训练过程与算法细节 三、Stable Diffusion的应用领域 1 图像生成与艺术创作 2 图像补全与修复 3 其他领域 四、Stable Diffusion的优势与挑战 &#x1f449;优势 &#x1f…

WSL下Ubuntu+RTX4090安装CUDA+cuDnn+Pytorch

安装驱动 首先需要明确的是&#xff0c;在WSL下安装Ubuntu&#xff0c;如果要使用主机的GPU卡&#xff0c;只需要在主机Windows上安装驱动&#xff0c;Linux中不需要安装驱动&#xff0c;可以在Linux中使用nvidia-smi命令查看驱动版本。 安装CUDA 避坑注意事项&#xff1a;如…

C++初阶:STL容器list的使用与初版自实现

目录 1. list的接口与使用1.1 默认成员函数1.2 迭代器与容量相关成员函数1.3 存储数据操作相关成员函数1.4 其他list操作成员函数 2. list的自实现2.1 list的自实现功能2.2 list的结点结构2.3 list的迭代器2.3 list的结构2.4 list迭代器的运算符重载2.5 list的成员函数 3. cons…

FreeCAD傻瓜教程之基准面的构建-在实体的表面上新建坐标、倾斜的平面、附加不同的台阶、旋转体等

目的&#xff1a;学会在已有模型的不同剖面上建立新的坐标系&#xff0c;并绘图&#xff1b;使得新图形仍然作为同一个零件实体的构件。 零、需求举例 在下列模型中&#xff0c;我们要在圆杆的顶部增加一个把手&#xff0c;如果点击圆杆顶部&#xff0c;则仅能在顶部圆形所在…

【Linux】Linux工具学习之git

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言一、账号注册1.1 GitHub与Gitee 二、构建仓库三、安装git 四、配置git五、克…

[金三银四] 操作系统上下文切换系列

图源&#xff1a; https://zhuanlan.zhihu.com/p/540717796 文章目录 2.11 cpu 的上下文切换2.12 协程的上下文切换2.13 线程的上下文切换2.14 进程的上下文切换2.15 中断上下文切换2.16 什么时候会发生进程的上下文切换2.17 什么时候会发生线程的上下文切换2.18 什么时候会发生…

cocos3.0 关于UI组件学习

Sprite 图片&#xff1a;官方文档 Size Mode: 1.Raw&#xff1a;原始大小 2.TRIMMED: 默认&#xff0c;会裁切原始图片透明像素 3.Custom&#xff1a;自定义&#xff0c;只要修改ContentSize&#xff0c;会自动设置 Type 1.Simple:普通,会铺满&#xff0c;一张图。 2.Sliced…

信号处理与分析——matlab记录

一、绘制信号分析频谱 1.代码 % 生成测试信号 Fs 3000; % 采样频率 t 0:1/Fs:1-1/Fs; % 时间向量 x1 1*sin(2*pi*50*t) 1*sin(2*pi*60*t); % 信号1 x2 1*sin(2*pi*150*t)1*sin(2*pi*270*t); % 信号2% 绘制信号图 subplot(2,2,1); plot(t,x1); title(信号x1 1*sin(…

Qt——2D画图

基础画图函数 矩形 painter.drawRect(50,50,200,100); 圆角矩形 painter.drawRoundRect(50,50,200,200,50,50); xRadius和yRadius分别以矩形宽度和高度的一半的百分比指定&#xff0c;并且应该在0.0到100.0的范围内 弧线 painter.drawArc(50,50,200,200, -90*16, 90*16);…

微服务(基础篇-003-Nacos)

目录 Nacos注册中心&#xff08;1&#xff09; 认识和安装Nacos&#xff08;1.1&#xff09; Nacos快速入门&#xff08;1.2&#xff09; 服务注册到Nacos(1.2.1) Nacos服务分级存储模型&#xff08;1.3&#xff09; 配置集群&#xff08;1.3.1&#xff09; 根据集群修改…

记录echarts各种地图json文件下载地址

今日绘图需要用到echarts的地图json文件&#xff0c;但是github上已经找不到了&#xff0c;后发现伟大的网友提供了地址如下&#xff1a;Index of /examples/data/asset/geohttps://echarts.apache.org/examples/data/asset/geo/

uniapp 打包后缺少maps模块和share模块的解决方案

缺失maps模块 我的应用 | 高德控制台 缺失share模块 QQ互联管理中心 微信开放平台