1# PluginComponent (系统接口) 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @dutie123--> 5<!--Designer: @lmleon--> 6<!--Tester: @fredyuan0912--> 7<!--Adviser: @HelloCrease--> 8 9提供外部应用组件嵌入式显示功能,即外部应用提供的UI可在本应用内显示。如需通过跨进程通信实现更新,请参考[@ohos.pluginComponent](../js-apis-plugincomponent.md)。 10 11 12> **说明:** 13> 14> - 该组件从API Version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 15> 16> - 本模块系统接口。 17 18## 子组件 19 20无 21 22 23## 接口 24 25PluginComponent(options: PluginComponentOptions) 26 27创建插件组件,用于显示外部应用提供的UI。 28 29**系统接口:** 此接口为系统接口。 30 31**系统能力:** SystemCapability.ArkUI.ArkUI.Full 32 33**参数:** 34 35| 参数名 | 类型 | 必填 | 说明 | 36| ------- | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ | 37| options | [PluginComponentOptions](#plugincomponentoptions18类型说明) | 是 | 定义用于构造插件组件的选项。 | 38 39## PluginComponentOptions<sup>18+</sup>类型说明 40 41定义用于构造插件组件的选项。 42 43> **说明:** 44> 45> 为规范匿名对象的定义,API 18版本修改了此处的元素定义。其中,保留了历史匿名对象的起始版本信息,会出现外层元素@since版本号高于内层元素版本号的情况,但这不影响接口的使用。 46 47**系统接口:** 此接口为系统接口。 48 49**系统能力:** SystemCapability.ArkUI.ArkUI.Full 50 51| 参数 | 类型 | 描述 | 52| ---------- | ------ | --------------------------- | 53| template<sup>9+</sup> | [PluginComponentTemplate](#plugincomponenttemplate9类型说明) | 组件模板,用于跟提供方定义的组件绑定。 | 54| data<sup>9+</sup> | any | 传给插件组件提供方使用的数据。 | 55 56## PluginComponentTemplate<sup>9+</sup>类型说明 57 58**系统接口:** 此接口为系统接口。 59 60**系统能力:** SystemCapability.ArkUI.ArkUI.Full 61 62| 参数 | 类型 | 描述 | 63| ---------- | ------ | --------------------------- | 64| source | string | 组件模板名。 | 65| bundleName | string | 提供方Ability的bundleName。 | 66 67## 属性 68 69必须显式设置组件宽高为非0有效值。 70 71**说明:** 72 73 模板支持两种提供方式: 74* 1.使用绝对路径进行资源提供:source字段填写模板绝对路径,bundleName不需要填写。仅适用于不需要加载资源的单独模板页面,不建议使用。 75* 2.通过应用包进行资源提供:bundleName字段需要填写应用包名;source字段填写相对hap包的模板相对路径,对于多hap场景,通过“相对路径&模块名称”的方式进行hap包的确认。 76 77 例如:{source: 'pages/PluginProviderExample.ets&entry', bundleName: 'com.example.provider'} 78 79 仅对FA模型支持source字段填写AbilityName、bundleName字段填写应用包名的方式进行资源提供。 80 81 例如:{source: 'plugin', bundleName: 'com.example.provider'} 82 83 84## 事件 85 86支持[绑定手势方法](ts-gesture-settings.md),并分发给提供方页面,在提供方页面内部处理。 87 88除支持[通用事件](ts-component-general-events.md),还支持以下事件: 89 90### onComplete 91 92onComplete(callback: VoidCallback) 93 94组件加载完成时触发回调。 95 96**系统接口:** 此接口为系统接口。 97 98**系统能力:** SystemCapability.ArkUI.ArkUI.Full 99 100**参数:** 101 102| 参数名 | 类型 | 必填 | 说明 | 103| ------- | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ | 104| callback | [VoidCallback](../../apis-basic-services-kit/js-apis-base.md#callback) | 是 | 回调函数,组件加载完成时触发的回调。 | 105 106### onError 107 108onError(callback: PluginErrorCallback) 109 110组件加载错误时触发回调。 111 112**系统接口:** 此接口为系统接口。 113 114**系统能力:** SystemCapability.ArkUI.ArkUI.Full 115 116**参数:** 117 118| 参数名 | 类型 | 必填 | 说明 | 119| --------- | ------------------------------------------------------------ | ---- | ----------------------------------------------- | 120| callback | [PluginErrorCallback](#pluginerrorcallback18类型说明) | 是 | 发生错误时调用回调。 | 121 122## PluginErrorCallback<sup>18+</sup>类型说明 123 124发生错误时调用回调。 125 126**系统接口:** 此接口为系统接口。 127 128**系统能力:** SystemCapability.ArkUI.ArkUI.Full 129 130| 参数 | 类型 | 描述 | 131| -------- | ------------------ | --------------------------- | 132| info | [PluginErrorData](#pluginerrordata18类型说明) | 发生错误时提供的数据。 | 133 134## PluginErrorData<sup>18+</sup>类型说明 135 136发生错误时提供的数据。 137 138> **说明:** 139> 140> 为规范匿名对象的定义,API 18版本修改了此处的元素定义。其中,保留了历史匿名对象的起始版本信息,会出现外层元素@since版本号高于内层元素版本号的情况,但这不影响接口的使用。 141 142**系统接口:** 此接口为系统接口。 143 144**系统能力:** SystemCapability.ArkUI.ArkUI.Full 145 146| 参数 | 类型 | 描述 | 147| ---------- | ------ | -------------------------- | 148| errcode<sup>9+</sup> | number | 错误码。 | 149| msg<sup>9+</sup> | string | 错误信息。 | 150 151错误码1为默认错误码,错误信息和处理建议详见下表: 152 153| 错误信息 | 描述 | 处理建议 | 154| ------ | -------------------------- | ----------------- | 155| package path is empty. | 包路径为空。 | 检查PluginComponentTemplate参数中source字段是否有误。 | 156| Query Active OsAccountIds failed! | 获取激活的用户ID失败。 | 检查Account服务是否异常,或检查应用是否具备用户ID查询权限。 | 157| Template source is empty. | 模板source为空。 | 检查PluginComponentTemplate参数中source字段是否有误。 | 158| Bms bundleManager is nullptr. | 获取BundleManager失败。 | 检查BMS服务是否异常,或检查应用是否具备ohos.permission.GET_BUNDLE_INFO_PRIVILEGED,ohos.permission.GET_BUNDLE_INFO,ohos.permission.REQUIRE_FORM权限。 | 159| App bundleName is empty. | 应用包名为空。 | 检查PluginComponentTemplate参数中bundleName字段是否有误。 | 160| Bms get bundleName failed! | 获取包名失败。 | 检查PluginComponentTemplate参数中bundleName字段是否有误,或检查bundleName字段对应的包是否已正确安装,或检查BMS服务是否异常,或检查应用是否具备ohos.permission.GET_BUNDLE_INFO_PRIVILEGED,ohos.permission.GET_BUNDLE_INFO,ohos.permission.REQUIRE_FORM权限。 | 161| Bms moduleResPaths is empty. | 插件包moduleResPaths属性为空。 | 检查bundleName字段对应的包的moduleResPaths属性是否异常,或检查BMS服务是否异常 | 162| Bms get hapPath failed! Cannot find hap according to BundleName and ModuleName! | 获取hapPath失败。 | 检查PluginComponentTemplate参数中bundleName字段是否有误,检查bundleName字段对应的模块是否已正确安装。 | 163 164 165## 示例(加载PluginComponent) 166 167本示例展示`PluginComponent`组件的基础使用方式,需要创建一个`bundleName`为"com.example.user"的[使用方应用](#组件使用方),和一个`bundleName`为"com.example.provider"的[提供方应用](#组件提供方)。应用项目构建完成后,具体测试步骤如下: 1681. 将两个应用的hap包安装到设备上; 1692. 打开使用方应用页面,使用方与提供方内容都正确显示; 1703. 分别点击使用方的“Register Push Listener”按钮和提供方的“Register Request Listener”按钮注册监听; 1714. 点击使用方的“Request”按钮向提供方发送事件,日志中打印“onRequestListener”相关信息; 1725. 点击提供方的“Push”按钮向使用方发送事件,日志中打印“onPushListener”相关信息。 173 174### 组件使用方 175 176使用方应用的`bundleName`为"com.example.user",包含一个页面。 177- `EntryAbility(UIAbility)`加载入口页面文件`ets/pages/Index.ets`,`Index.ets`内容如下: 178 ```ts 179 import plugin from "./plugin_component"; 180 181 interface Info { 182 errcode: number, 183 msg: string 184 } 185 186 @Entry 187 @Component 188 struct PluginUserExample { 189 build() { 190 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 191 Text('Hello World') 192 .fontSize(50) 193 .fontWeight(FontWeight.Bold) 194 Button('Register Push Listener') 195 .fontSize(30) 196 .width(400) 197 .height(100) 198 .margin({ top: 20 }) 199 .onClick(() => { 200 plugin.onListener(); 201 console.info("Button('Register Push Listener')"); 202 }) 203 Button('Request') 204 .fontSize(50) 205 .width(400) 206 .height(100) 207 .margin({ top: 20 }) 208 .onClick(() => { 209 plugin.Request(); 210 console.info("Button('Request')"); 211 }) 212 PluginComponent({ 213 // 提供方 214 template: { source: 'pages/Index.ets&entry', bundleName: 'com.example.provider' }, 215 data: { 'countDownStartValue': 'new countDownStartValue' } 216 }).size({ width: 500, height: 350 }) 217 .onComplete(() => { 218 console.info("onComplete"); 219 }) 220 .onError((info: Info) => { 221 console.error("onError" + info.errcode + ":" + info.msg); 222 }) 223 } 224 .width('100%') 225 .height('100%') 226 } 227 } 228 ``` 229- 根据模型类型,将对应的[Plugin组件工具代码](#plugin组件工具)拷贝至项目的`ets/pages/plugin_component.js`文件中。 230- 在`module.json5`配置文件中增加`requestPermissions`标签,允许使用方查询其他应用信息: 231 ```json 232 "requestPermissions": [ 233 { 234 "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", 235 "usedScene": { 236 "abilities": [ 237 "EntryAbility" 238 ], 239 "when": "inuse" 240 } 241 } 242 ] 243 ``` 244 245### 组件提供方 246 247提供方应用的`bundleName`为"com.example.provider",包含一个页面。 248- `EntryAbility(UIAbility)`加载入口页面文件`ets/pages/Index.ets`,`Index.ets`内容如下: 249 ```ts 250 import plugin from "./plugin_component"; 251 252 @Entry 253 @Component 254 struct PluginProviderExample { 255 @State message: string = 'no click!'; 256 257 build() { 258 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 259 Button('Register Request Listener') 260 .fontSize(30) 261 .width(400) 262 .height(100) 263 .margin({ top: 20 }) 264 .onClick(() => { 265 plugin.onListener(); 266 console.info("Button('Register Request Listener')"); 267 }) 268 Button('Push') 269 .fontSize(30) 270 .width(400) 271 .height(100) 272 .margin({ top: 20 }) 273 .onClick(() => { 274 plugin.Push(); 275 this.message = "Button('Push')"; 276 console.info("Button('Push')"); 277 }) 278 Text(this.message) 279 .height(150) 280 .fontSize(30) 281 .padding(5) 282 .margin(5) 283 }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 }) 284 } 285 } 286 ``` 287- 根据模型类型,将对应的[Plugin组件工具代码](#plugin组件工具)拷贝至项目的`ets/pages/plugin_component.js`文件中。 288 289### Plugin组件工具 290 291Plugin组件工具,用于使用方与提供方之间进行通信。需要根据模型类型选择对应代码,并拷贝至项目中。 292 293#### FA模型 294```js 295// 当前示例代码仅适用于FA模型 296import pluginComponentManager from '@ohos.pluginComponent' 297 298var providerBundleName = 'com.example.provider' 299var providerAbilityName = 'com.example.provider.EntryAbility' 300var providerName = 'Index' 301 302// push事件监听 303function onPushListener(source, template, data, extraData) { 304 console.info("onPushListener template.source=" + template.source) 305 console.info("onPushListener template.ability=" + template.ability) 306 console.info("onPushListener data=" + JSON.stringify(data)) 307 console.info("onPushListener extraData=" + JSON.stringify(extraData)) 308} 309 310// request事件监听 311function onRequestListener(source, name, data) 312{ 313 console.info("onRequestListener name=" + name); 314 console.info("onRequestListener data=" + JSON.stringify(data)); 315 return {template:"pluginTemplate", data:data}; 316} 317 318export default { 319 // 注册监听事件 320 onListener() { 321 pluginComponentManager.on("push", onPushListener) 322 pluginComponentManager.on("request", onRequestListener) 323 }, 324 Push() { 325 // 组件提供方主动发送事件,want: 提供方信息 326 pluginComponentManager.push( 327 { 328 want: { 329 bundleName: providerBundleName, 330 abilityName: providerAbilityName, 331 }, 332 name: providerName, 333 data: { 334 "key_1": "plugin component push data", 335 "key_2": 12345 336 }, 337 extraData: { 338 "extra_str": "this is push event" 339 }, 340 jsonPath: "", 341 }, 342 (err, data) => { 343 console.info("push_callback: push ok!"); 344 } 345 ) 346 }, 347 Request() { 348 // 组件使用方主动发送事件,want: 提供方信息 349 pluginComponentManager.request({ 350 want: { 351 bundleName: providerBundleName, 352 abilityName: providerAbilityName, 353 }, 354 name: providerName, 355 data: { 356 "key_1": "plugin component request data", 357 "key_2": 67890 358 }, 359 jsonPath: "", 360 }, 361 (err, data) => { 362 console.info("request_callback: componentTemplate.ability=" + data.componentTemplate.ability) 363 console.info("request_callback: componentTemplate.source=" + data.componentTemplate.source) 364 console.info("request_callback: data=" + JSON.stringify(data.data)) 365 console.info("request_callback: extraData=" + JSON.stringify(data.extraData)) 366 } 367 ) 368 } 369} 370``` 371 372#### Stage模型 373```js 374// 当前示例代码仅适用于Stage模型 375import pluginComponentManager from '@ohos.pluginComponent' 376 377var userBundleName = 'com.example.user' 378var userAbilityName = 'com.example.user.EntryAbility' 379var providerBundleName = 'com.example.provider' 380var providerAbilityName = 'com.example.provider.EntryAbility' 381var providerName = 'Index' 382 383// push事件监听 384function onPushListener(source, template, data, extraData) { 385 console.info("onPushListener template.source=" + template.source) 386 console.info("onPushListener template.ability=" + template.ability) 387 console.info("onPushListener data=" + JSON.stringify(data)) 388 console.info("onPushListener extraData=" + JSON.stringify(extraData)) 389} 390 391// request事件监听 392function onRequestListener(source, name, data) { 393 console.info("onRequestListener name=" + name) 394 console.info("onRequestListener data=" + JSON.stringify(data)) 395 return { template: "pluginTemplate", data: data } 396} 397 398export default { 399 // 注册监听事件 400 onListener() { 401 pluginComponentManager.on("push", onPushListener) 402 pluginComponentManager.on("request", onRequestListener) 403 }, 404 Push() { 405 // 组件提供方主动发送事件,owner:使用方,target:提供方 406 pluginComponentManager.push( 407 { 408 owner: { 409 bundleName: userBundleName, 410 abilityName: userAbilityName, 411 }, 412 target: { 413 bundleName: providerBundleName, 414 abilityName: providerAbilityName, 415 }, 416 name: providerName, 417 data: { 418 "key_1": "plugin component push data", 419 "key_2": 12345 420 }, 421 extraData: { 422 "extra_str": "this is push event" 423 }, 424 jsonPath: "", 425 }, 426 (err, data) => { 427 console.info("push_callback: push ok!"); 428 } 429 ) 430 }, 431 Request() { 432 // 组件使用方主动发送事件,owner:使用方,target:提供方 433 pluginComponentManager.request({ 434 owner: { 435 bundleName: userBundleName, 436 abilityName: userAbilityName, 437 }, 438 target: { 439 bundleName: providerBundleName, 440 abilityName: providerAbilityName, 441 }, 442 name: providerName, 443 data: { 444 "key_1": "plugin component request data", 445 "key_2": 67890 446 }, 447 jsonPath: "", 448 }, 449 (err, data) => { 450 console.info("request_callback: componentTemplate.ability=" + data.componentTemplate.ability) 451 console.info("request_callback: componentTemplate.source=" + data.componentTemplate.source) 452 console.info("request_callback: data=" + JSON.stringify(data.data)) 453 console.info("request_callback: extraData=" + JSON.stringify(data.extraData)) 454 } 455 ) 456 } 457} 458``` 459