UIExtensionAbility
概述
[UIExtensionAbility]是UI類型的ExtensionAbility組件,需要與[UIExtensionComponent]一起配合使用,開(kāi)發(fā)者可以在UIAbility的頁(yè)面中通過(guò)UIExtensionComponent嵌入提供方應(yīng)用的UIExtensionAbility提供的UI。UIExtensionAbility會(huì)在獨(dú)立于UIAbility的進(jìn)程中運(yùn)行,完成其頁(yè)面的布局和渲染。常用于有進(jìn)程隔離訴求的系統(tǒng)彈窗、狀態(tài)欄、膠囊等模塊化開(kāi)發(fā)的場(chǎng)景。
說(shuō)明:
開(kāi)發(fā)前請(qǐng)熟悉鴻蒙開(kāi)發(fā)指導(dǎo)文檔 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
當(dāng)前UIExtensionAbility和UIExtensionComponent僅支持系統(tǒng)應(yīng)用使用。
生命周期
[UIExtensionAbility]提供了onCreate、onSessionCreate、onSessionDestroy、onForeground、onBackground和onDestroy生命周期回調(diào),根據(jù)需要重寫(xiě)對(duì)應(yīng)的回調(diào)方法。
- [ onCreate ]:當(dāng)UIExtensionAbility創(chuàng)建時(shí)回調(diào),執(zhí)行初始化業(yè)務(wù)邏輯操作。
- [ onSessionCreate ]:當(dāng)UIExtensionAbility界面內(nèi)容對(duì)象創(chuàng)建后調(diào)用。
- [ onSessionDestroy ]:當(dāng)UIExtensionAbility界面內(nèi)容對(duì)象銷(xiāo)毀后調(diào)用。
- [ onForeground ]:當(dāng)UIExtensionAbility從后臺(tái)轉(zhuǎn)到前臺(tái)時(shí)觸發(fā)。
- [ onBackground ]:當(dāng)UIExtensionAbility從前臺(tái)轉(zhuǎn)到后臺(tái)時(shí)觸發(fā)。
- [ onDestroy ]:當(dāng)UIExtensionAbility銷(xiāo)毀時(shí)回調(diào),可以執(zhí)行資源清理等操作。
選擇合適的UIExtensionAbility進(jìn)程模型
UIExtensionAbility支持多實(shí)例,每個(gè)嵌入式顯示對(duì)應(yīng)一個(gè)UIExtensionAbility實(shí)例。多實(shí)例場(chǎng)景下默認(rèn)是多進(jìn)程,可配置多進(jìn)程模型。 UIExtensionAbility支持多實(shí)例,每個(gè)嵌入式顯示對(duì)應(yīng)一個(gè)UIExtensionAbility實(shí)例。 當(dāng)應(yīng)用中存在多個(gè)UIExtensionAbility實(shí)例,這些實(shí)例可以為多個(gè)獨(dú)立進(jìn)程,也可以共用同一個(gè)進(jìn)程,還可以分為多組、同組實(shí)例共用同一個(gè)進(jìn)程。通過(guò)module.json5配置文件中的extensionProcessMode字段,即可為選擇對(duì)應(yīng)的進(jìn)程模型,三種模型對(duì)比如下:
進(jìn)程模型 | extensionProcessMode字段配置 | 說(shuō)明 |
---|---|---|
同一bundle中所有UIExtensionAbility共進(jìn)程 | bundle | UIExtensionAbility實(shí)例之間的通信無(wú)需跨IPC通信;實(shí)例之間的狀態(tài)不獨(dú)立,會(huì)存在相互影響。 |
相同name的UIExtensionAbility共進(jìn)程 | type | 將同UIExtensionAbility類配置在同一個(gè)進(jìn)程下,便于應(yīng)用針對(duì)UIExtensionAbility類型對(duì)實(shí)例進(jìn)行管理。 |
每個(gè)UIExtensionAbility為獨(dú)立進(jìn)程 | instance | UIExtensionAbility實(shí)例之間的狀態(tài)不會(huì)彼此影響,安全性更高;實(shí)例之間只能通過(guò)跨進(jìn)程進(jìn)行通信。 |
Bundle中的所有UIExtensionAbility共進(jìn)程
同一個(gè)bundle下的UIExtensionAbility配置在同一個(gè)進(jìn)程中,便于多實(shí)例間的通信。需要關(guān)注的是,各個(gè)實(shí)例之間的狀態(tài)會(huì)彼此影響,當(dāng)進(jìn)程中的一個(gè)實(shí)例異常退出,將導(dǎo)致進(jìn)程中所有的實(shí)例也都會(huì)退出;
圖1 bundle模型配置示意圖
Index.ets示例代碼如下:
@Entry
@Component
struct Index {
@State message: string = 'UIExtension UserA';
private myProxy: UIExtensionProxy | undefined = undefined;
build() {
Row() {
Column() {
Text(this.message)
.fontSize(30)
.size({ width: '100%', height: '50'})
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
UIExtensionComponent(
{
bundleName: 'com.samples.uiextensionability',
abilityName: 'UIExtensionProvider',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 10})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
UIExtensionComponent(
{
bundleName: 'com.samples.uiextension2',
abilityName: 'UIExtensionProviderB',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 50})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
}
.width('100%')
}
.height('100%')
}
}
圖2 根據(jù)上述代碼,生成的Index頁(yè)面如下:
采用該進(jìn)程模型,進(jìn)程名格式為: process name [{bundleName}:{UIExtensionAbility的類型}] 例如,process name [com.ohos.intentexecutedemo:xxx]。 圖3 進(jìn)程模型展示
同UIExtensionAbility類的所有UIExtensionAbility共進(jìn)程
根據(jù)UIExtensionAbility類進(jìn)行分配進(jìn)程,拉起多個(gè)同樣的UIExtensionAbility實(shí)例時(shí),這些實(shí)例將配置在同一個(gè)進(jìn)程中。將同UIExtensionAbility類配置在同一個(gè)進(jìn)程下,方便應(yīng)用針對(duì)UIExtensionAbility類型對(duì)實(shí)例進(jìn)行管理;
圖4 type模型配置示意圖
Index.ets示例代碼如下:
@Entry
@Component
struct Index {
@State message: string = 'UIExtension User';
private myProxy: UIExtensionProxy | undefined = undefined;
build() {
Row() {
Column() {
Text(this.message)
.fontSize(30)
.size({ width: '100%', height: '50'})
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
UIExtensionComponent(
{
bundleName: 'com.samples.uiextensionability',
abilityName: 'UIExtensionProviderA',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 10})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
UIExtensionComponent(
{
bundleName: 'com.samples.uiextensionability',
abilityName: 'UIExtensionProviderB',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 50})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
}
.width('100%')
}
.height('100%')
}
}
圖5 根據(jù)上述代碼,生成的Index頁(yè)面如下:
采用該進(jìn)程模型,進(jìn)程名格式為: process name [{bundleName}:{UIExtensionAbility名}] 例如,process name [com.ohos.intentexecutedemo:xxx]。 圖6 進(jìn)程模型展示
UIExtensionAbility實(shí)例獨(dú)立進(jìn)程
根據(jù)UIExtensionAbility實(shí)例進(jìn)行分配進(jìn)程,配置了instance的UIExtensionAbility實(shí)例,將每個(gè)實(shí)例獨(dú)立一個(gè)進(jìn)程。獨(dú)立進(jìn)程的場(chǎng)景下,UIExtensionAbility實(shí)例之間只能通過(guò)跨進(jìn)程進(jìn)行通信,但實(shí)例之間的狀態(tài)不會(huì)彼此影響,安全性更高;
圖7 instance模型配置示意圖
Index.ets示例代碼如下:
@Entry
@Component
struct Index {
@State message: string = 'UIExtension User'
private myProxy: UIExtensionProxy | undefined = undefined;
build() {
Row() {
Column() {
Text(this.message)
.fontSize(30)
.size({ width: '100%', height: '50'})
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
UIExtensionComponent(
{
bundleName: 'com.samples.uiextensionability',
abilityName: 'UIExtensionProvider',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 10})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
UIExtensionComponent(
{
bundleName: 'com.samples.uiextensionability',
abilityName: 'UIExtensionProvider',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 50})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
}
.width('100%')
}
.height('100%')
}
}
圖8 根據(jù)上述代碼,生成的Index頁(yè)面如下:
采用該進(jìn)程模型,進(jìn)程名格式為: process name [{bundleName}:{UIExtensionAbility的類型}: {實(shí)例后綴}] 例如,process name [com.ohos.intentexecutedemo:xxx:n]。 圖9 進(jìn)程模型展示
UIExtensionAbility通過(guò)[UIExtensionContext]和[UIExtensionContentSession]提供相關(guān)能力。本文描述中稱被啟動(dòng)的UIExtensionAbility為提供方,稱啟動(dòng)UIExtensionAbility的UIExtensionComponent組件為使用方。
開(kāi)發(fā)步驟
為了便于表述,本例中將提供UIExtensionAbility能力的一方稱為提供方,將啟動(dòng)UIExtensionAbility的一方稱為使用方,本例中使用方通過(guò)UIExtensionComponent容器啟動(dòng)UIExtensionAbility。
開(kāi)發(fā)UIExtensionAbility提供方
開(kāi)發(fā)者在實(shí)現(xiàn)一個(gè)UIExtensionAbility提供方時(shí),需要在DevEco Studio工程中手動(dòng)新建一個(gè)UIExtensionAbility,具體步驟如下。
- 在工程Module對(duì)應(yīng)的ets目錄下,右鍵選擇“New > Directory”,新建一個(gè)目錄并命名為uiextensionability。
- 在uiextensionability目錄,右鍵選擇“New > File”,新建一個(gè).ts文件并命名為UIExtensionAbility.ts。
- 打開(kāi)UIExtensionAbility.ts,導(dǎo)入U(xiǎn)IExtensionAbility的依賴包,自定義類繼承UIExtensionAbility并實(shí)現(xiàn)onCreate、onSessionCreate、onSessionDestroy、onForeground、onBackground和onDestroy生命周期回調(diào)。
import Want from '@ohos.app.ability.Want'; import UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility'; import UIExtensionContentSession from '@ohos.app.ability. UIExtensionContentSession'; const TAG: string = '[testTag] UIExtAbility ' export default class UIExtAbility extends UIExtensionAbility { onCreate() { console.log(TAG, `onCreate`); } onForeground() { console.log(TAG, `onForeground`); } onBackground() { console.log(TAG, `onBackground`); } onDestroy() { console.log(TAG, `onDestroy`); } onSessionCreate(want: Want, session: UIExtensionContentSession) { console.log(TAG, `onSessionCreate, want: ${JSON.stringify(want)}}`); let storage: LocalStorage = new LocalStorage(); storage.setOrCreate('session', session); session.loadContent('pages/Extension',storage); } onSessionDestroy(session: UIExtensionContentSession) { console.log(TAG, `onSessionDestroy`); } }
- UIExtensionAbility的onSessionCreate中加載了入口頁(yè)面文件pages/extension.ets, 并在entrysrcmainresourcesbaseprofilemain_pages.json文件中添加"pages/Extension"聲明,extension.ets內(nèi)容如下:
import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; let storage = LocalStorage.GetShared(); const TAG: string = `[testTag] ExtensionPage`; @Entry(storage) @Component struct Extension { @State message: string = `UIExtension provider`; private session: UIExtensionContentSession | undefined = storage.get< UIExtensionContentSession >('session'); onPageShow() { console.info(TAG, 'show'); } build() { Row() { Column() { Text(this.message) .fontSize(30) .fontWeight(FontWeight.Bold) .textAlign(TextAlign.Center) Button("send data") .width('80%') .type(ButtonType.Capsule) .margin({ top:20 }) .onClick(() = > { this.session?.sendData({ "data": 543321}); }) Button("terminate self") .width('80%') .type(ButtonType.Capsule) .margin({ top:20 }) .onClick(() = > { this.session?.terminateSelf(); storage.clear(); }) Button("terminate self with result") .width('80%') .type(ButtonType.Capsule) .margin({ top:20 }) .onClick(() = > { this.session?.terminateSelfWithResult({ resultCode: 0, want: { bundleName:"com.example.uiextensiondemo", parameters: { "result": 123456 } } }) }) } } .height('100%') } }
- 在工程Module對(duì)應(yīng)的[module.json5配置文件]中注冊(cè)UIExtensionAbility,type標(biāo)簽需要設(shè)置為UIExtensionAbility中配置的對(duì)應(yīng)類型,srcEntry標(biāo)簽表示當(dāng)前UIExtensionAbility組件所對(duì)應(yīng)的代碼路徑。extensionProcessMode標(biāo)簽標(biāo)識(shí)多實(shí)例的進(jìn)程模型,此處以"bundle"為例。
{ "module": { "extensionAbilities": [ { "name": "UIExtensionProvider", "srcEntry": "./ets/uiextensionability/UIExtensionAbility.ets", "description": "UIExtensionAbility", "type": "sys/commonUI", "exported": true, "extensionProcessMode": "bundle" }, ] } }
開(kāi)發(fā)UIExtensionAbility使用方
開(kāi)發(fā)者可以在UIAbility的頁(yè)面中通過(guò)UIExtensionComponent容器加載自己應(yīng)用內(nèi)的UIExtensionAbility。 如在首頁(yè)文件:pages/Index.ets中添加如下內(nèi)容:
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
@Entry
@Component
struct Index {
@State message: string = 'UIExtension User';
private myProxy: UIExtensionProxy | undefined = undefined;
build() {
Row() {
Column() {
Text(this.message)
.fontSize(30)
.size({ width: '100%', height: '50'})
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
UIExtensionComponent(
{
bundleName: 'com.example.uiextensiondemo',
abilityName: 'UIExtensionProvider',
moduleName: 'entry',
parameters: {
'ability.want.params.uiExtensionType': 'sys/commonUI',
}
})
.onRemoteReady((proxy) = > {
this.myProxy = proxy;
})
.onReceive((data) = > {
this.message = JSON.stringify(data);
})
.onResult((data) = > {
this.message = JSON.stringify(data);
})
.onRelease((code) = > {
this.message = "release code:" + code;
})
.offset({ x: 0, y: 30})
.size({ width: 300, height: 300})
.border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
Button("sendData")
.type(ButtonType.Capsule)
.offset({ x: 0,y: 60})
.width('80%')
.type(ButtonType.Capsule)
.margin({
top: 20
})
.onClick(() = > {
this.myProxy?.send({
"data": 123456,
"message": "data from component"
})
})
}
.width('100%')
}
.height('100%')
}
}
審核編輯 黃宇
-
框架
+關(guān)注
關(guān)注
0文章
398瀏覽量
17404 -
鴻蒙
+關(guān)注
關(guān)注
57文章
2302瀏覽量
42689
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論