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