UIExtensionAbility
概述
[UIExtensionAbility]是UI類型的ExtensionAbility組件,需要與[UIExtensionComponent]一起配合使用,開發者可以在UIAbility的頁面中通過UIExtensionComponent嵌入提供方應用的UIExtensionAbility提供的UI。UIExtensionAbility會在獨立于UIAbility的進程中運行,完成其頁面的布局和渲染。常用于有進程隔離訴求的系統彈窗、狀態欄、膠囊等模塊化開發的場景。
說明:
開發前請熟悉鴻蒙開發指導文檔 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
當前UIExtensionAbility和UIExtensionComponent僅支持系統應用使用。
生命周期
[UIExtensionAbility]提供了onCreate、onSessionCreate、onSessionDestroy、onForeground、onBackground和onDestroy生命周期回調,根據需要重寫對應的回調方法。
- [ onCreate ]:當UIExtensionAbility創建時回調,執行初始化業務邏輯操作。
- [ onSessionCreate ]:當UIExtensionAbility界面內容對象創建后調用。
- [ onSessionDestroy ]:當UIExtensionAbility界面內容對象銷毀后調用。
- [ onForeground ]:當UIExtensionAbility從后臺轉到前臺時觸發。
- [ onBackground ]:當UIExtensionAbility從前臺轉到后臺時觸發。
- [ onDestroy ]:當UIExtensionAbility銷毀時回調,可以執行資源清理等操作。
選擇合適的UIExtensionAbility進程模型
UIExtensionAbility支持多實例,每個嵌入式顯示對應一個UIExtensionAbility實例。多實例場景下默認是多進程,可配置多進程模型。 UIExtensionAbility支持多實例,每個嵌入式顯示對應一個UIExtensionAbility實例。 當應用中存在多個UIExtensionAbility實例,這些實例可以為多個獨立進程,也可以共用同一個進程,還可以分為多組、同組實例共用同一個進程。通過module.json5配置文件中的extensionProcessMode字段,即可為選擇對應的進程模型,三種模型對比如下:
進程模型 | extensionProcessMode字段配置 | 說明 |
---|---|---|
同一bundle中所有UIExtensionAbility共進程 | bundle | UIExtensionAbility實例之間的通信無需跨IPC通信;實例之間的狀態不獨立,會存在相互影響。 |
相同name的UIExtensionAbility共進程 | type | 將同UIExtensionAbility類配置在同一個進程下,便于應用針對UIExtensionAbility類型對實例進行管理。 |
每個UIExtensionAbility為獨立進程 | instance | UIExtensionAbility實例之間的狀態不會彼此影響,安全性更高;實例之間只能通過跨進程進行通信。 |
Bundle中的所有UIExtensionAbility共進程
同一個bundle下的UIExtensionAbility配置在同一個進程中,便于多實例間的通信。需要關注的是,各個實例之間的狀態會彼此影響,當進程中的一個實例異常退出,將導致進程中所有的實例也都會退出;
圖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 根據上述代碼,生成的Index頁面如下:
采用該進程模型,進程名格式為: process name [{bundleName}:{UIExtensionAbility的類型}] 例如,process name [com.ohos.intentexecutedemo:xxx]。 圖3 進程模型展示
同UIExtensionAbility類的所有UIExtensionAbility共進程
根據UIExtensionAbility類進行分配進程,拉起多個同樣的UIExtensionAbility實例時,這些實例將配置在同一個進程中。將同UIExtensionAbility類配置在同一個進程下,方便應用針對UIExtensionAbility類型對實例進行管理;
圖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 根據上述代碼,生成的Index頁面如下:
采用該進程模型,進程名格式為: process name [{bundleName}:{UIExtensionAbility名}] 例如,process name [com.ohos.intentexecutedemo:xxx]。 圖6 進程模型展示
UIExtensionAbility實例獨立進程
根據UIExtensionAbility實例進行分配進程,配置了instance的UIExtensionAbility實例,將每個實例獨立一個進程。獨立進程的場景下,UIExtensionAbility實例之間只能通過跨進程進行通信,但實例之間的狀態不會彼此影響,安全性更高;
圖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 根據上述代碼,生成的Index頁面如下:
采用該進程模型,進程名格式為: process name [{bundleName}:{UIExtensionAbility的類型}: {實例后綴}] 例如,process name [com.ohos.intentexecutedemo:xxx:n]。 圖9 進程模型展示
UIExtensionAbility通過[UIExtensionContext]和[UIExtensionContentSession]提供相關能力。本文描述中稱被啟動的UIExtensionAbility為提供方,稱啟動UIExtensionAbility的UIExtensionComponent組件為使用方。
開發步驟
為了便于表述,本例中將提供UIExtensionAbility能力的一方稱為提供方,將啟動UIExtensionAbility的一方稱為使用方,本例中使用方通過UIExtensionComponent容器啟動UIExtensionAbility。
開發UIExtensionAbility提供方
開發者在實現一個UIExtensionAbility提供方時,需要在DevEco Studio工程中手動新建一個UIExtensionAbility,具體步驟如下。
- 在工程Module對應的ets目錄下,右鍵選擇“New > Directory”,新建一個目錄并命名為uiextensionability。
- 在uiextensionability目錄,右鍵選擇“New > File”,新建一個.ts文件并命名為UIExtensionAbility.ts。
- 打開UIExtensionAbility.ts,導入UIExtensionAbility的依賴包,自定義類繼承UIExtensionAbility并實現onCreate、onSessionCreate、onSessionDestroy、onForeground、onBackground和onDestroy生命周期回調。
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中加載了入口頁面文件pages/extension.ets, 并在entrysrcmainresourcesbaseprofilemain_pages.json文件中添加"pages/Extension"聲明,extension.ets內容如下:
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對應的[module.json5配置文件]中注冊UIExtensionAbility,type標簽需要設置為UIExtensionAbility中配置的對應類型,srcEntry標簽表示當前UIExtensionAbility組件所對應的代碼路徑。extensionProcessMode標簽標識多實例的進程模型,此處以"bundle"為例。
{ "module": { "extensionAbilities": [ { "name": "UIExtensionProvider", "srcEntry": "./ets/uiextensionability/UIExtensionAbility.ets", "description": "UIExtensionAbility", "type": "sys/commonUI", "exported": true, "extensionProcessMode": "bundle" }, ] } }
開發UIExtensionAbility使用方
開發者可以在UIAbility的頁面中通過UIExtensionComponent容器加載自己應用內的UIExtensionAbility。 如在首頁文件:pages/Index.ets中添加如下內容:
`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%')
}
}
審核編輯 黃宇
-
框架
+關注
關注
0文章
403瀏覽量
17475 -
鴻蒙
+關注
關注
57文章
2339瀏覽量
42805
發布評論請先 登錄
相關推薦
評論