UIAbility是系統(tǒng)調(diào)度的最小單元。在設(shè)備內(nèi)的功能模塊之間跳轉(zhuǎn)時(shí),會(huì)涉及到啟動(dòng)特定的UIAbility,該UIAbility可以是應(yīng)用內(nèi)的其他UIAbility,也可以是其他應(yīng)用的UIAbility(例如啟動(dòng)三方支付UIAbility)。
本文將從如下場(chǎng)景分別介紹設(shè)備內(nèi)UIAbility間的交互方式。對(duì)于跨設(shè)備的應(yīng)用組件交互,請(qǐng)參見(jiàn) 應(yīng)用組件跨設(shè)備交互(流轉(zhuǎn))。
- 啟動(dòng)應(yīng)用內(nèi)的UIAbility
- 啟動(dòng)應(yīng)用內(nèi)的UIAbility并獲取返回結(jié)果
- 啟動(dòng)其他應(yīng)用的UIAbility
- 啟動(dòng)其他應(yīng)用的UIAbility并獲取返回結(jié)果
- 啟動(dòng)UIAbility指定窗口模式(僅對(duì)系統(tǒng)應(yīng)用開(kāi)放)
- 啟動(dòng)UIAbility的指定頁(yè)面
- 通過(guò)Call調(diào)用實(shí)現(xiàn)UIAbility交互(僅對(duì)系統(tǒng)應(yīng)用開(kāi)放)
啟動(dòng)應(yīng)用內(nèi)的UIAbility
當(dāng)一個(gè)應(yīng)用內(nèi)包含多個(gè)UIAbility時(shí),存在應(yīng)用內(nèi)啟動(dòng)UIAbility的場(chǎng)景。例如在支付應(yīng)用中從入口UIAbility啟動(dòng)收付款UIAbility。
假設(shè)應(yīng)用中有兩個(gè)UIAbility:EntryAbility和FuncAbility(可以在同一個(gè)Module中,也可以在不同的Module中),需要從EntryAbility的頁(yè)面中啟動(dòng)FuncAbility。
- 在EntryAbility中,通過(guò)調(diào)用
startAbility()
方法啟動(dòng)UIAbility,want 為UIAbility實(shí)例啟動(dòng)的入口參數(shù),其中bundleName為待啟動(dòng)應(yīng)用的Bundle名稱,abilityName為待啟動(dòng)的Ability名稱,moduleName在待啟動(dòng)的UIAbility屬于不同的Module時(shí)添加,parameters為自定義信息參數(shù)。示例中的context的獲取方式請(qǐng)參見(jiàn) 獲取UIAbility的上下文信息。
import common from '@ohos.app.ability.common';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
import hilog from '@ohos.hilog';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
private context = getContext(this) as common.UIAbilityContext;
build() {
...
Button()
.onClick(() => {
// context為Ability對(duì)象的成員,在非Ability對(duì)象內(nèi)部調(diào)用需要
// 將Context對(duì)象傳遞過(guò)去
let wantInfo: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.myapplication',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityA',
parameters: { // 自定義信息
info: '來(lái)自EntryAbility Page_UIAbilityComponentsInteractive頁(yè)面'
},
}
// context為調(diào)用方UIAbility的UIAbilityContext
this.context.startAbility(wantInfo).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.');
}).catch((error: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.');
});
})
}
}
- 在FuncAbility的
onCreate()
生命周期回調(diào)文件中接收EntryAbility傳遞過(guò)來(lái)的參數(shù)。
import UIAbility from '@ohos.app.ability.UIAbility';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import Want from '@ohos.app.ability.Want';
export default class FuncAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 接收調(diào)用方UIAbility傳過(guò)來(lái)的參數(shù)
let funcAbilityWant = want;
let info = funcAbilityWant?.parameters?.info;
// ...
}
}
說(shuō)明:
被拉起的FuncAbility中,可以通過(guò)獲取傳遞過(guò)來(lái)的want
參數(shù)的parameters
來(lái)獲取拉起方UIAbility的PID、Bundle Name等信息。
- 在FuncAbility業(yè)務(wù)完成之后,如需要停止當(dāng)前UIAbility實(shí)例,在FuncAbility中通過(guò)調(diào)用
terminateSelf()
方法實(shí)現(xiàn)。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
...
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
// context為需要停止的UIAbility實(shí)例的AbilityContext
context.terminateSelf((err) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate Self. Code is ${err.code}, message is ${err.message}`);
return;
}
});
})
}
}
說(shuō)明:
調(diào)用terminateSelf()
方法停止當(dāng)前UIAbility實(shí)例時(shí),默認(rèn)會(huì)保留該實(shí)例的快照(Snapshot),即在最近任務(wù)列表中仍然能查看到該實(shí)例對(duì)應(yīng)的任務(wù)。如不需要保留該實(shí)例的快照,可以在其對(duì)應(yīng)UIAbility的 module.json5配置文件中,將 abilities標(biāo)簽的removeMissionAfterTerminate字段配置為true。
- 如需要關(guān)閉應(yīng)用所有的UIAbility實(shí)例,可以調(diào)用 ApplicationContext 的
killAllProcesses()
方法實(shí)現(xiàn)關(guān)閉應(yīng)用所有的進(jìn)程。
啟動(dòng)應(yīng)用內(nèi)的UIAbility并獲取返回結(jié)果
在一個(gè)EntryAbility啟動(dòng)另外一個(gè)FuncAbility時(shí),希望在被啟動(dòng)的FuncAbility完成相關(guān)業(yè)務(wù)后,能將結(jié)果返回給調(diào)用方。例如在應(yīng)用中將入口功能和帳號(hào)登錄功能分別設(shè)計(jì)為兩個(gè)獨(dú)立的UIAbility,在帳號(hào)登錄UIAbility中完成登錄操作后,需要將登錄的結(jié)果返回給入口UIAbility。
- 在EntryAbility中,調(diào)用
startAbilityForResult()
接口啟動(dòng)FuncAbility,異步回調(diào)中的data用于接收FuncAbility停止自身后返回給EntryAbility的信息。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityA',
parameters: { // 自定義信息
info: '來(lái)自EntryAbility UIAbilityComponentsInteractive頁(yè)面'
}
};
context.startAbilityForResult(want).then((data) => {
// ...
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
- 在FuncAbility停止自身時(shí),需要調(diào)用
terminateSelfWithResult()
方法,入?yún)bilityResult為FuncAbility需要返回給EntryAbility的信息。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
const TAG: string = '[Page_FuncAbilityA]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_FuncAbilityA {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
const RESULT_CODE: number = 1001;
let abilityResult: common.AbilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityB',
parameters: {
info: '來(lái)自FuncAbility Index頁(yè)面'
},
},
};
context.terminateSelfWithResult(abilityResult, (err) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`);
return;
}
});
})
}
}
- FuncAbility停止自身后,EntryAbility通過(guò)
startAbilityForResult()
方法回調(diào)接收被FuncAbility返回的信息,RESULT_CODE需要與前面的數(shù)值保持一致。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
import promptAction from '@ohos.promptAction';
const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
const RESULT_CODE: number = 1001;
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityA',
parameters: { // 自定義信息
info: '來(lái)自EntryAbility UIAbilityComponentsInteractive頁(yè)面'
}
};
context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被調(diào)用方UIAbility返回的信息
let info = data.want?.parameters?.info;
hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? '');
if (info !== null) {
promptAction.showToast({
message: JSON.stringify(info)
});
}
}
hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? '');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
啟動(dòng)其他應(yīng)用的UIAbility
啟動(dòng)其他應(yīng)用的UIAbility,通常用戶只需要完成一個(gè)通用的操作(例如需要選擇一個(gè)文檔應(yīng)用來(lái)查看某個(gè)文檔的內(nèi)容信息)。系統(tǒng)會(huì)根據(jù)調(diào)用方的want參數(shù)來(lái)識(shí)別和啟動(dòng)匹配到的應(yīng)用UIAbility。
啟動(dòng)UIAbility有 顯式Want啟動(dòng)和隱式Want啟動(dòng) 兩種方式。
-
顯式Want啟動(dòng):?jiǎn)?dòng)一個(gè)確定應(yīng)用的UIAbility,在want參數(shù)中需要設(shè)置該應(yīng)用bundleName和abilityName,當(dāng)需要拉起某個(gè)明確的UIAbility時(shí),通常使用顯式Want啟動(dòng)方式。
-
隱式Want啟動(dòng):根據(jù)匹配條件由用戶選擇啟動(dòng)哪一個(gè)UIAbility,即不明確指出要啟動(dòng)哪一個(gè)UIAbility(abilityName參數(shù)未設(shè)置),在調(diào)用
startAbility()
方法時(shí),其入?yún)ant中指定了一系列的entities字段(表示目標(biāo)UIAbility額外的類別信息,如瀏覽器、視頻播放器)和actions字段(表示要執(zhí)行的通用操作,如查看、分享、應(yīng)用詳情等)等參數(shù)信息,然后由系統(tǒng)去分析want,并幫助找到合適的UIAbility來(lái)啟動(dòng)。當(dāng)需要拉起其他應(yīng)用的UIAbility時(shí),開(kāi)發(fā)者通常不知道用戶設(shè)備中應(yīng)用的安裝情況,也無(wú)法確定目標(biāo)應(yīng)用的bundleName和abilityName,通常使用隱式Want啟動(dòng)方式。
本文主要講解如何通過(guò)隱式Want啟動(dòng)其他應(yīng)用的UIAbility。
- 將多個(gè)待匹配的文檔應(yīng)用安裝到設(shè)備,在其對(duì)應(yīng)UIAbility的 module.json5配置文件 中,配置skills標(biāo)簽的entities字段和actions字段。
{
"module": {
"abilities": [
{
...
"skills": [
{
"entities": [
...
"entity.system.default"
],
"actions": [
...
"ohos.want.action.viewData"
]
}
]
}
]
}
}
- 在調(diào)用方want參數(shù)中的entities和action需要被包含在待匹配UIAbility的skills配置的entities和actions中。系統(tǒng)匹配到符合entities和actions參數(shù)條件的UIAbility后,會(huì)彈出選擇框展示匹配到的UIAbility實(shí)例列表供用戶選擇使用。
import common from '@ohos.app.ability.common';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
import hilog from '@ohos.hilog';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: 'com.samples.stagemodelabilityinteraction',
action: 'ohos.want.action.viewData',
// entities can be omitted.
entities: ['entity.system.default']
};
// context為調(diào)用方UIAbility的UIAbilityContext
context.startAbility(want).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting FuncAbility.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start FuncAbility. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
效果示意如下圖所示,點(diǎn)擊“打開(kāi)PDF文檔”時(shí),會(huì)彈出選擇框供用戶選擇。
- 在文檔應(yīng)用使用完成之后,如需要停止當(dāng)前UIAbility實(shí)例,通過(guò)調(diào)用
terminateSelf()
方法實(shí)現(xiàn)。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
const TAG: string = '[Page_FromStageModel]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_FromStageModel {
@State message: string = 'Hello World'
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
// context為需要停止的UIAbility實(shí)例的AbilityContext
context.terminateSelf((err) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);
return;
}
});
})
}
}
啟動(dòng)其他應(yīng)用的UIAbility并獲取返回結(jié)果
當(dāng)使用隱式Want啟動(dòng)其他應(yīng)用的UIAbility并希望獲取返回結(jié)果時(shí),調(diào)用方需要使用 startAbilityForResult()
方法啟動(dòng)目標(biāo)UIAbility。例如主應(yīng)用中需要啟動(dòng)三方支付并獲取支付結(jié)果。
- 在支付應(yīng)用對(duì)應(yīng)UIAbility的 module.json5配置文件 中,配置skills的entities字段和actions字段。
{
"module": {
"abilities": [
{
...
"skills": [
{
"entities": [
...
"entity.system.default"
],
"actions": [
...
"ohos.want.action.editData"
]
}
]
}
]
}
}
- 調(diào)用方使用
startAbilityForResult()
方法啟動(dòng)支付應(yīng)用的UIAbility,在調(diào)用方want參數(shù)中的entities和action需要被包含在待匹配UIAbility的skills標(biāo)簽配置的entities和actions中。異步回調(diào)中的data用于后續(xù)接收支付UIAbility停止自身后返回給調(diào)用方的信息。系統(tǒng)匹配到符合entities和actions參數(shù)條件的UIAbility后,會(huì)彈出選擇框展示匹配到的UIAbility實(shí)例列表供用戶選擇使用。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityA',
parameters: { // 自定義信息
info: '來(lái)自EntryAbility UIAbilityComponentsInteractive頁(yè)面'
}
};
context.startAbilityForResult(want).then((data) => {
// ...
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
- 在支付UIAbility完成支付之后,需要調(diào)用
terminateSelfWithResult()
方法實(shí)現(xiàn)停止自身,并將abilityResult參數(shù)信息返回給調(diào)用方。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
const TAG: string = '[Page_FuncAbilityA]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_FuncAbilityA {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
const RESULT_CODE: number = 1001;
let abilityResult: common.AbilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityB',
parameters: {
info: '來(lái)自FuncAbility Index頁(yè)面'
},
},
};
context.terminateSelfWithResult(abilityResult, (err) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`);
return;
}
});
})
}
}
- 在調(diào)用方
startAbilityForResult()
方法回調(diào)中接收支付應(yīng)用返回的信息,RESULT_CODE需要與前面terminateSelfWithResult()
返回的數(shù)值保持一致。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
import promptAction from '@ohos.promptAction';
const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
const RESULT_CODE: number = 1001;
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityA',
parameters: { // 自定義信息
info: '來(lái)自EntryAbility UIAbilityComponentsInteractive頁(yè)面'
}
};
context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被調(diào)用方UIAbility返回的信息
let info = data.want?.parameters?.info;
hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? '');
if (info !== null) {
promptAction.showToast({
message: JSON.stringify(info)
});
}
}
hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? '');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
啟動(dòng)UIAbility指定窗口模式(僅對(duì)系統(tǒng)應(yīng)用開(kāi)放)
當(dāng)用戶打開(kāi)應(yīng)用時(shí),應(yīng)用程序會(huì)以不同的窗口模式進(jìn)行展示,即啟動(dòng)UIAbility的窗口模式。應(yīng)用程序可以啟動(dòng)為全屏模式,懸浮窗模式或分屏模式。
全屏模式是指應(yīng)用程序啟動(dòng)后,占據(jù)整個(gè)屏幕,用戶無(wú)法同時(shí)查看其他窗口或應(yīng)用程序。全屏模式通常適用于那些要求用戶專注于特定任務(wù)或界面的應(yīng)用程序。
懸浮窗模式是指應(yīng)用程序啟動(dòng)后,以浮動(dòng)窗口的形式顯示在屏幕上,用戶可以輕松切換到其他窗口或應(yīng)用程序。懸浮窗通常適用于需要用戶同時(shí)處理多個(gè)任務(wù)的應(yīng)用程序。
分屏模式允許用戶在同一屏幕上同時(shí)運(yùn)行兩個(gè)應(yīng)用程序,其中一個(gè)應(yīng)用程序占據(jù)屏幕左側(cè)/上側(cè)的一部分,另一個(gè)應(yīng)用程序占據(jù)右側(cè)/下側(cè)的一部分。分屏模式主要用于提高用戶的多任務(wù)處理效率。
使用 startAbility()
方法啟動(dòng)UIAbility時(shí),可以通過(guò)在入?yún)⒅性黾?StartOptions 參數(shù)的windowMode屬性來(lái)配置啟動(dòng)UIAbility的窗口模式。
說(shuō)明:
- 如果在使用
startAbility()
方法啟動(dòng)UIAbility時(shí),入?yún)⒅形粗付?StartOptions 參數(shù)的windowMode屬性,那么UIAbility將以系統(tǒng)默認(rèn)的窗口展示形態(tài)啟動(dòng)。 - 為了確保啟動(dòng)的UIAbility展示形態(tài)能夠被支持,需要在該UIAbility對(duì)應(yīng)的 module.json5配置文件中 abilities標(biāo)簽的supportWindowMode字段確認(rèn)啟動(dòng)的展示形態(tài)被支持。
以下是具體的操作步驟,以懸浮窗模式為例,假設(shè)需要從EntryAbility的頁(yè)面中啟動(dòng)FuncAbility:
- 在調(diào)用
startAbility()
方法時(shí),增加 StartOptions 參數(shù)。 - 在 StartOptions 參數(shù)中設(shè)置
windowMode
字段為WINDOW_MODE_FLOATING
,表示啟動(dòng)的UIAbility將以懸浮窗的形式展示。 -
windowMode
屬性僅適用于系統(tǒng)應(yīng)用,三方應(yīng)用可以使用displayId
屬性。
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import StartOptions from '@ohos.app.ability.StartOptions';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbilityB',
parameters: { // 自定義信息
info: '來(lái)自EntryAbility Index頁(yè)面'
}
};
let options: StartOptions = {
windowMode: AbilityConstant.WindowMode.WINDOW_MODE_FLOATING
};
// context為調(diào)用方UIAbility的UIAbilityContext
context.startAbility(want, options).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ability.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
效果示意如下圖所示。
啟動(dòng)UIAbility的指定頁(yè)面
概述
一個(gè)UIAbility可以對(duì)應(yīng)多個(gè)頁(yè)面,在不同的場(chǎng)景下啟動(dòng)該UIAbility時(shí)需要展示不同的頁(yè)面,例如從一個(gè)UIAbility的頁(yè)面中跳轉(zhuǎn)到另外一個(gè)UIAbility時(shí),希望啟動(dòng)目標(biāo)UIAbility的指定頁(yè)面。
UIAbility的啟動(dòng)分為兩種情況:UIAbility冷啟動(dòng)和UIAbility熱啟動(dòng)。
- UIAbility冷啟動(dòng):指的是UIAbility實(shí)例處于完全關(guān)閉狀態(tài)下被啟動(dòng),這需要完整地加載和初始化UIAbility實(shí)例的代碼、資源等。
- UIAbility熱啟動(dòng):指的是UIAbility實(shí)例已經(jīng)啟動(dòng)并在前臺(tái)運(yùn)行過(guò),由于某些原因切換到后臺(tái),再次啟動(dòng)該UIAbility實(shí)例,這種情況下可以快速恢復(fù)UIAbility實(shí)例的狀態(tài)。
本文主要講解 目標(biāo)UIAbility冷啟動(dòng) 兩種啟動(dòng)指定頁(yè)面的場(chǎng)景,以及在講解啟動(dòng)指定頁(yè)面之前會(huì)講解到在調(diào)用方如何指定啟動(dòng)頁(yè)面。
調(diào)用方UIAbility指定啟動(dòng)頁(yè)面
調(diào)用方UIAbility啟動(dòng)另外一個(gè)UIAbility時(shí),通常需要跳轉(zhuǎn)到指定的頁(yè)面。例如FuncAbility包含兩個(gè)頁(yè)面(Index對(duì)應(yīng)首頁(yè),Second對(duì)應(yīng)功能A頁(yè)面),此時(shí)需要在傳入的want參數(shù)中配置指定的頁(yè)面路徑信息,可以通過(guò)want中的parameters參數(shù)增加一個(gè)自定義參數(shù)傳遞頁(yè)面跳轉(zhuǎn)信息。
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
deviceId: '', // deviceId為空表示本設(shè)備
bundleName: 'com.samples.stagemodelabilityinteraction',
moduleName: 'entry', // moduleName非必選
abilityName: 'FuncAbility',
parameters: { // 自定義參數(shù)傳遞頁(yè)面信息
router: 'FuncA'
}
};
// context為調(diào)用方UIAbility的UIAbilityContext
context.startAbility(want).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ability.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
目標(biāo)UIAbility冷啟動(dòng)
目標(biāo)UIAbility冷啟動(dòng)時(shí),在目標(biāo)UIAbility的onCreate()
生命周期回調(diào)中,接收調(diào)用方傳過(guò)來(lái)的參數(shù)。然后在目標(biāo)UIAbility的onWindowStageCreate()
生命周期回調(diào)中,解析EntryAbility傳遞過(guò)來(lái)的want參數(shù),獲取到需要加載的頁(yè)面信息url,傳入windowStage.loadContent()
方法。
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
export default class FuncAbility extends UIAbility {
funcAbilityWant: Want | undefined = undefined;
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 接收調(diào)用方UIAbility傳過(guò)來(lái)的參數(shù)
this.funcAbilityWant = want;
}
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
url = 'pages/Page_ColdStartUp';
}
windowStage.loadContent(url, (err, data) => {
// ...
});
}
}
目標(biāo)UIAbility熱啟動(dòng)
在應(yīng)用開(kāi)發(fā)中,會(huì)遇到目標(biāo)UIAbility實(shí)例之前已經(jīng)啟動(dòng)過(guò)的場(chǎng)景,這時(shí)再次啟動(dòng)目標(biāo)UIAbility時(shí),不會(huì)重新走初始化邏輯,只會(huì)直接觸發(fā)onNewWant()
生命周期方法。為了實(shí)現(xiàn)跳轉(zhuǎn)到指定頁(yè)面,需要在onNewWant()
中解析參數(shù)進(jìn)行處理。
例如短信應(yīng)用和聯(lián)系人應(yīng)用配合使用的場(chǎng)景。
- 用戶先打開(kāi)短信應(yīng)用,短信應(yīng)用的UIAbility實(shí)例啟動(dòng),顯示短信應(yīng)用的主頁(yè)。
- 用戶將設(shè)備回到桌面界面,短信應(yīng)用進(jìn)入后臺(tái)運(yùn)行狀態(tài)。
- 用戶打開(kāi)聯(lián)系人應(yīng)用,找到聯(lián)系人張三。
- 用戶點(diǎn)擊聯(lián)系人張三的短信按鈕,會(huì)重新啟動(dòng)短信應(yīng)用的UIAbility實(shí)例。
- 由于短信應(yīng)用的UIAbility實(shí)例已經(jīng)啟動(dòng)過(guò)了,此時(shí)會(huì)觸發(fā)該UIAbility的
onNewWant()
回調(diào),而不會(huì)再走onCreate()
和onWindowStageCreate()
等初始化邏輯。
圖1 目標(biāo)UIAbility熱啟動(dòng)
開(kāi)發(fā)步驟如下所示。
- 冷啟動(dòng)短信應(yīng)用的UIAbility實(shí)例時(shí),在
onWindowStageCreate()
生命周期回調(diào)中,通過(guò)調(diào)用getUIContext()
接口獲取UI上下文實(shí)例UIContext
對(duì)象。
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
import { UIContext } from '@ohos.arkui.UIContext';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EntryAbility]';
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want | undefined = undefined;
uiContext: UIContext | undefined = undefined;
// ...
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
url = 'pages/Page_ColdStartUp';
}
windowStage.loadContent(url, (err, data) => {
if (err.code) {
return;
}
let windowClass: window.Window;
windowStage.getMainWindow((err, data) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to obtain the main window. Code is ${err.code}, message is ${err.message}`);
return;
}
windowClass = data;
this.uiContext = windowClass.getUIContext();
})
});
}
}
- 在短信應(yīng)用UIAbility的
onNewWant()
回調(diào)中解析調(diào)用方傳遞過(guò)來(lái)的want參數(shù),通過(guò)調(diào)用UIContext中的getRouter()
方法獲取Router
對(duì)象,并進(jìn)行指定頁(yè)面的跳轉(zhuǎn)。此時(shí)再次啟動(dòng)該短信應(yīng)用的UIAbility實(shí)例時(shí),即可跳轉(zhuǎn)到該短信應(yīng)用的UIAbility實(shí)例的指定頁(yè)面。
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';
import { Router, UIContext } from '@ohos.arkui.UIContext';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EntryAbility]';
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want | undefined = undefined;
uiContext: UIContext | undefined = undefined;
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (want?.parameters?.router && want.parameters.router === 'funcB') {
let funcAUrl = 'pages/Page_HotStartUp';
if (this.uiContext) {
let router: Router = this.uiContext.getRouter();
router.pushUrl({
url: funcAUrl
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to push url. Code is ${err.code}, message is ${err.message}`);
});
}
}
}
// ...
}
說(shuō)明:
當(dāng)被調(diào)用方 UIAbility組件啟動(dòng)模式 設(shè)置為multiton啟動(dòng)模式時(shí),每次啟動(dòng)都會(huì)創(chuàng)建一個(gè)新的實(shí)例,那么 onNewWant() 回調(diào)就不會(huì)被用到。
通過(guò)Call調(diào)用實(shí)現(xiàn)UIAbility交互(僅對(duì)系統(tǒng)應(yīng)用開(kāi)放)
Call調(diào)用是UIAbility能力的擴(kuò)展,它為UIAbility提供一種能夠被外部調(diào)用并與外部進(jìn)行通信的能力。Call調(diào)用支持前臺(tái)與后臺(tái)兩種啟動(dòng)方式,使UIAbility既能被拉起到前臺(tái)展示UI,也可以在后臺(tái)被創(chuàng)建并運(yùn)行。Call調(diào)用在調(diào)用方與被調(diào)用方間建立了IPC通信,因此應(yīng)用開(kāi)發(fā)者可通過(guò)Call調(diào)用實(shí)現(xiàn)不同UIAbility之間的數(shù)據(jù)共享。
Call調(diào)用的核心接口是startAbilityByCall()
方法,與startAbility()
接口的不同之處在于:
- startAbilityByCall支持前臺(tái)與后臺(tái)兩種啟動(dòng)方式,而
startAbility()
僅支持前臺(tái)啟動(dòng)。 - 調(diào)用方可使用
startAbilityByCall()
所返回的Caller對(duì)象與被調(diào)用方進(jìn)行通信,而startAbility()
不具備通信能力。
Call調(diào)用的使用場(chǎng)景主要包括:
- 需要與被啟動(dòng)的UIAbility進(jìn)行通信。
- 希望被啟動(dòng)的UIAbility在后臺(tái)運(yùn)行。
表1?Call調(diào)用相關(guān)名詞解釋
名詞 | 描述 |
---|---|
CallerAbility | 進(jìn)行Call調(diào)用的UIAbility(調(diào)用方)。 |
CalleeAbility | 被Call調(diào)用的UIAbility(被調(diào)用方)。 |
Caller | 實(shí)際對(duì)象,由startAbilityByCall接口返回,CallerAbility可使用Caller與CalleeAbility進(jìn)行通信。 |
Callee | 實(shí)際對(duì)象,被CalleeAbility持有,可與Caller進(jìn)行通信。 |
Call調(diào)用示意圖如下所示。
圖1?Call調(diào)用示意圖
- CallerAbility調(diào)用startAbilityByCall接口獲取Caller,并使用Caller對(duì)象的call方法向CalleeAbility發(fā)送數(shù)據(jù)。
- CalleeAbility持有一個(gè)Callee對(duì)象,通過(guò)Callee的on方法注冊(cè)回調(diào)函數(shù),當(dāng)接收到Caller發(fā)送的數(shù)據(jù)時(shí)將會(huì)調(diào)用對(duì)應(yīng)的回調(diào)函數(shù)。
說(shuō)明:
- 當(dāng)前僅支持系統(tǒng)應(yīng)用使用Call調(diào)用。
- CalleeAbility的啟動(dòng)模式需要為單實(shí)例。
- Call調(diào)用既支持本地(設(shè)備內(nèi))Call調(diào)用,也支持跨設(shè)備Call調(diào)用,下面介紹設(shè)備內(nèi)Call調(diào)用方法。
接口說(shuō)明
Call功能主要接口如下表所示。具體的API詳見(jiàn) 接口文檔。
表2?Call功能主要接口
接口名 | 描述 |
---|---|
startAbilityByCall(want:?Want):?Promise | 啟動(dòng)指定UIAbility并獲取其Caller通信接口,默認(rèn)為后臺(tái)啟動(dòng),通過(guò)配置want可實(shí)現(xiàn)前臺(tái)啟動(dòng),詳見(jiàn) 接口文檔。AbilityContext與ServiceExtensionContext均支持該接口。 |
on(method:?string,?callback:?CalleeCallBack):?void | 通用組件Callee注冊(cè)method對(duì)應(yīng)的callback方法。 |
off(method:?string):?void | 通用組件Callee解注冊(cè)method的callback方法。 |
call(method:?string,?data:?rpc.Parcelable):?Promise | 向通用組件Callee發(fā)送約定序列化數(shù)據(jù)。 |
callWithResult(method:?string,?data:?rpc.Parcelable):?Promise<rpc.MessageSequence> | 向通用組件Callee發(fā)送約定序列化數(shù)據(jù),?并將Callee返回的約定序列化數(shù)據(jù)帶回。 |
release():?void | 釋放通用組件的Caller通信接口。 |
on(type:?“release”,?callback:?OnReleaseCallback):?void | 注冊(cè)通用組件通信斷開(kāi)監(jiān)聽(tīng)通知。 |
設(shè)備內(nèi)通過(guò)Call調(diào)用實(shí)現(xiàn)UIAbility交互,涉及如下兩部分開(kāi)發(fā):
- 創(chuàng)建Callee被調(diào)用端
- 訪問(wèn)Callee被調(diào)用端
開(kāi)發(fā)步驟(創(chuàng)建Callee被調(diào)用端)
在Callee被調(diào)用端,需要實(shí)現(xiàn)指定方法的數(shù)據(jù)接收回調(diào)函數(shù)、數(shù)據(jù)的序列化及反序列化方法。在需要接收數(shù)據(jù)期間,通過(guò)on接口注冊(cè)監(jiān)聽(tīng),無(wú)需接收數(shù)據(jù)時(shí)通過(guò)off接口解除監(jiān)聽(tīng)。
- 配置UIAbility的啟動(dòng)模式。
例如將CalleeAbility配置為單實(shí)例模式singleton
。
- 導(dǎo)入U(xiǎn)IAbility模塊。
import UIAbility from '@ohos.app.ability.UIAbility';
- 定義約定的序列化數(shù)據(jù)。 調(diào)用端及被調(diào)用端發(fā)送接收的數(shù)據(jù)格式需協(xié)商一致,如下示例約定數(shù)據(jù)由number和string組成。
import type rpc from '@ohos.rpc';
class MyParcelable {
num: number = 0;
str: string = '';
constructor(num: number, string: string) {
this.num = num;
this.str = string;
};
mySequenceable(num, string): void {
this.num = num;
this.str = string;
};
marshalling(messageSequence: rpc.MessageSequence): boolean {
messageSequence.writeInt(this.num);
messageSequence.writeString(this.str);
return true;
};
unmarshalling(messageSequence: rpc.MessageSequence): boolean {
this.num = messageSequence.readInt();
this.str = messageSequence.readString();
return true;
};
};
- 實(shí)現(xiàn)Callee.on監(jiān)聽(tīng)及Callee.off解除監(jiān)聽(tīng)。
被調(diào)用端Callee的監(jiān)聽(tīng)函數(shù)注冊(cè)時(shí)機(jī),取決于應(yīng)用開(kāi)發(fā)者。注冊(cè)監(jiān)聽(tīng)之前的數(shù)據(jù)不會(huì)被處理,取消監(jiān)聽(tīng)之后的數(shù)據(jù)不會(huì)被處理。如下示例在UIAbility的onCreate注冊(cè)’MSG_SEND_METHOD’監(jiān)聽(tīng),在onDestroy取消監(jiān)聽(tīng),收到序列化數(shù)據(jù)后作相應(yīng)處理并返回,應(yīng)用開(kāi)發(fā)者根據(jù)實(shí)際需要做相應(yīng)處理。具體示例代碼如下:
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
import hilog from '@ohos.hilog';
import Logger from '../utils/Logger';
import type rpc from '@ohos.rpc';
import type { Caller } from '@ohos.app.ability.UIAbility';
const MSG_SEND_METHOD: string = 'CallSendMsg';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[CalleeAbility]';
class MyParcelable {
num: number = 0;
str: string = '';
constructor(num: number, string: string) {
this.num = num;
this.str = string;
}
mySequenceable(num, string): void {
this.num = num;
this.str = string;
}
marshalling(messageSequence: rpc.MessageSequence): boolean {
messageSequence.writeInt(this.num);
messageSequence.writeString(this.str);
return true;
};
unmarshalling(messageSequence: rpc.MessageSequence): boolean {
this.num = messageSequence.readInt();
this.str = messageSequence.readString();
return true;
};
};
function sendMsgCallback(data: rpc.MessageSequence): rpc.Parcelable {
hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'CalleeSortFunc called');
// 獲取Caller發(fā)送的序列化數(shù)據(jù)
let receivedData: MyParcelable = new MyParcelable(0, '');
data.readParcelable(receivedData);
hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', `receiveData[${receivedData.num}, ${receivedData.str}]`);
let num: number = receivedData.num;
// 作相應(yīng)處理
// 返回序列化數(shù)據(jù)result給Caller
return new MyParcelable(num + 1, `send ${receivedData.str} succeed`) as rpc.Parcelable;
}
export default class CalleeAbility extends UIAbility {
caller: Caller | undefined;
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
try {
this.callee.on(MSG_SEND_METHOD, sendMsgCallback);
} catch (error) {
hilog.error(DOMAIN_NUMBER, TAG, '%{public}s', `Failed to register. Error is ${error}`);
};
}
releaseCall(): void {
try {
if (this.caller) {
this.caller.release();
this.caller = undefined;
}
Logger.info('caller release succeed');
} catch (error) {
Logger.info(`caller release failed with ${error}`);
};
}
onDestroy(): void {
try {
this.callee.off(MSG_SEND_METHOD);
hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Callee OnDestroy');
this.releaseCall();
} catch (error) {
hilog.error(DOMAIN_NUMBER, TAG, '%{public}s', `Failed to register. Error is ${error}`);
};
}
}
開(kāi)發(fā)步驟(訪問(wèn)Callee被調(diào)用端)
- 導(dǎo)入U(xiǎn)IAbility模塊。
import UIAbility from '@ohos.app.ability.UIAbility';
- 獲取Caller通信接口。 UIAbilityContext屬性實(shí)現(xiàn)了startAbilityByCall方法,用于獲取指定通用組件的Caller通信接口。如下示例通過(guò)this.context獲取UIAbility實(shí)例的context屬性,使用startAbilityByCall拉起Callee被調(diào)用端并獲取Caller通信接口,注冊(cè)Caller的onRelease監(jiān)聽(tīng)。應(yīng)用開(kāi)發(fā)者根據(jù)實(shí)際需要做相應(yīng)處理。
import { Caller } from '@ohos.app.ability.UIAbility';
import { BusinessError } from '@ohos.base';
import common from '@ohos.app.ability.common';
import promptAction from '@ohos.promptAction';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
caller: Caller | undefined = undefined;
// 注冊(cè)caller的release監(jiān)聽(tīng)
private regOnRelease(caller: Caller): void {
hilog.info(DOMAIN_NUMBER, TAG, `caller is ${caller}`);
try {
caller.on('release', (msg: string) => {
hilog.info(DOMAIN_NUMBER, TAG, `caller onRelease is called ${msg}`);
})
hilog.info(DOMAIN_NUMBER, TAG, 'succeeded in registering on release.');
} catch (err) {
let code = (err as BusinessError).code;
let message = (err as BusinessError).message;
hilog.error(DOMAIN_NUMBER, TAG, `Failed to caller register on release. Code is ${code}, message is ${message}`);
}
;
}
build() {
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
bundleName: 'com.samples.stagemodelabilityinteraction',
abilityName: 'CalleeAbility',
parameters: { // 自定義信息
info: 'CallSendMsg'
}
};
context.startAbilityByCall(want).then((caller: Caller) => {
hilog.info(DOMAIN_NUMBER, TAG, `Succeeded in starting ability.Code is ${caller}`);
if (caller === undefined) {
hilog.info(DOMAIN_NUMBER, TAG, 'get caller failed');
return;
}
else {
hilog.info(DOMAIN_NUMBER, TAG, 'get caller success');
this.regOnRelease(caller);
promptAction.showToast({
message: $r('app.string.CallerSuccess')
});
}
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
});
})
}
}
為了能讓大家更好的學(xué)習(xí)鴻蒙(HarmonyOS NEXT)開(kāi)發(fā)技術(shù),這邊特意整理了《鴻蒙開(kāi)發(fā)學(xué)習(xí)手冊(cè)》(共計(jì)890頁(yè)),希望對(duì)大家有所幫助:https://qr21.cn/FV7h05
《鴻蒙開(kāi)發(fā)學(xué)習(xí)手冊(cè)》:
如何快速入門:https://qr21.cn/FV7h05
- 基本概念
- 構(gòu)建第一個(gè)ArkTS應(yīng)用
- ……
開(kāi)發(fā)基礎(chǔ)知識(shí):https://qr21.cn/FV7h05
- 應(yīng)用基礎(chǔ)知識(shí)
- 配置文件
- 應(yīng)用數(shù)據(jù)管理
- 應(yīng)用安全管理
- 應(yīng)用隱私保護(hù)
- 三方應(yīng)用調(diào)用管控機(jī)制
- 資源分類與訪問(wèn)
- 學(xué)習(xí)ArkTS語(yǔ)言
- ……
基于ArkTS 開(kāi)發(fā):https://qr21.cn/FV7h05
- Ability開(kāi)發(fā)
- UI開(kāi)發(fā)
- 公共事件與通知
- 窗口管理
- 媒體
- 安全
- 網(wǎng)絡(luò)與鏈接
- 電話服務(wù)
- 數(shù)據(jù)管理
- 后臺(tái)任務(wù)(Background Task)管理
- 設(shè)備管理
- 設(shè)備使用信息統(tǒng)計(jì)
- DFX
- 國(guó)際化開(kāi)發(fā)
- 折疊屏系列
- ……
鴻蒙開(kāi)發(fā)面試真題(含參考答案):https://qr18.cn/F781PH
鴻蒙開(kāi)發(fā)面試大盤集篇(共計(jì)319頁(yè)):https://qr18.cn/F781PH
1.項(xiàng)目開(kāi)發(fā)必備面試題
2.性能優(yōu)化方向
3.架構(gòu)方向
4.鴻蒙開(kāi)發(fā)系統(tǒng)底層方向
5.鴻蒙音視頻開(kāi)發(fā)方向
6.鴻蒙車載開(kāi)發(fā)方向
7.鴻蒙南向開(kāi)發(fā)方向文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-849286.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-849286.html
到了這里,關(guān)于HarmonyOS 應(yīng)用開(kāi)發(fā)之UIAbility組件間交互(設(shè)備內(nèi))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!