UIAbility組件間交互(設(shè)備內(nèi))

2024-01-25 12:16 更新

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)。

本章節(jié)將從如下場(chǎng)景分別介紹設(shè)備內(nèi)UIAbility間的交互方式。

啟動(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。

  1. 在EntryAbility中,通過調(diào)用startAbility()方法啟動(dòng)UIAbility,want為UIAbility實(shí)例啟動(dòng)的入口參數(shù),其中bundleName為待啟動(dòng)應(yīng)用的Bundle名稱,abilityName為待啟動(dòng)的UIAbility名稱,moduleName在待啟動(dòng)的UIAbility屬于不同的Module時(shí)添加,parameters為自定義信息參數(shù)。示例中的context的獲取方式參見獲取UIAbility的Context屬性。

    1. let wantInfo = {
    2. deviceId: '', // deviceId為空表示本設(shè)備
    3. bundleName: 'com.example.myapplication',
    4. abilityName: 'FuncAbility',
    5. moduleName: 'module1', // moduleName非必選
    6. parameters: { // 自定義信息
    7. info: '來(lái)自EntryAbility Index頁(yè)面',
    8. },
    9. }
    10. // context為調(diào)用方UIAbility的AbilityContext
    11. this.context.startAbility(wantInfo).then(() => {
    12. // ...
    13. }).catch((err) => {
    14. // ...
    15. })
  2. 在FuncAbility的生命周期回調(diào)文件中接收EntryAbility傳遞過來(lái)的參數(shù)。

    1. import UIAbility from '@ohos.app.ability.UIAbility';
    2. import Window from '@ohos.window';
    3. export default class FuncAbility extends UIAbility {
    4. onCreate(want, launchParam) {
    5. // 接收調(diào)用方UIAbility傳過來(lái)的參數(shù)
    6. let funcAbilityWant = want;
    7. let info = funcAbilityWant?.parameters?.info;
    8. // ...
    9. }
    10. }
  3. 在FuncAbility業(yè)務(wù)完成之后,如需要停止當(dāng)前UIAbility實(shí)例,在FuncAbility中通過調(diào)用terminateSelf()方法實(shí)現(xiàn)。

    1. // context為需要停止的UIAbility實(shí)例的AbilityContext
    2. this.context.terminateSelf((err) => {
    3. // ...
    4. });

啟動(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。

  1. 在EntryAbility中,調(diào)用startAbilityForResult()接口啟動(dòng)FuncAbility,異步回調(diào)中的data用于接收FuncAbility停止自身后返回給EntryAbility的信息。示例中的context的獲取方式參見獲取UIAbility的Context屬性。

    1. let wantInfo = {
    2. deviceId: '', // deviceId為空表示本設(shè)備
    3. bundleName: 'com.example.myapplication',
    4. abilityName: 'FuncAbility',
    5. moduleName: 'module1', // moduleName非必選
    6. parameters: { // 自定義信息
    7. info: '來(lái)自EntryAbility Index頁(yè)面',
    8. },
    9. }
    10. // context為調(diào)用方UIAbility的AbilityContext
    11. this.context.startAbilityForResult(wantInfo).then((data) => {
    12. // ...
    13. }).catch((err) => {
    14. // ...
    15. })
  2. 在FuncAbility停止自身時(shí),需要調(diào)用terminateSelfWithResult()方法,入?yún)bilityResult為FuncAbility需要返回給EntryAbility的信息。

    1. const RESULT_CODE: number = 1001;
    2. let abilityResult = {
    3. resultCode: RESULT_CODE,
    4. want: {
    5. bundleName: 'com.example.myapplication',
    6. abilityName: 'FuncAbility',
    7. moduleName: 'module1',
    8. parameters: {
    9. info: '來(lái)自FuncAbility Index頁(yè)面',
    10. },
    11. },
    12. }
    13. // context為被調(diào)用方UIAbility的AbilityContext
    14. this.context.terminateSelfWithResult(abilityResult, (err) => {
    15. // ...
    16. });
  3. FuncAbility停止自身后,EntryAbility通過startAbilityForResult()方法回調(diào)接收被FuncAbility返回的信息,RESULT_CODE需要與前面的數(shù)值保持一致。

    1. const RESULT_CODE: number = 1001;
    2. // ...
    3. // context為調(diào)用方UIAbility的AbilityContext
    4. this.context.startAbilityForResult(want).then((data) => {
    5. if (data?.resultCode === RESULT_CODE) {
    6. // 解析被調(diào)用方UIAbility返回的信息
    7. let info = data.want?.parameters?.info;
    8. // ...
    9. }
    10. }).catch((err) => {
    11. // ...
    12. })

啟動(dòng)其他應(yīng)用的UIAbility

啟動(dòng)其他應(yīng)用的UIAbility,通常用戶只需要完成一個(gè)通用的操作(例如需要選擇一個(gè)文檔應(yīng)用來(lái)查看某個(gè)文檔的內(nèi)容信息),推薦使用隱式Want啟動(dòng)。系統(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í),開發(fā)者通常不知道用戶設(shè)備中應(yīng)用的安裝情況,也無(wú)法確定目標(biāo)應(yīng)用的bundleName和abilityName,通常使用隱式Want啟動(dòng)方式。

本章節(jié)主要講解如何通過隱式Want啟動(dòng)其他應(yīng)用的UIAbility。

  1. 將多個(gè)待匹配的文檔應(yīng)用安裝到設(shè)備,在其對(duì)應(yīng)UIAbility的module.json5配置文件中,配置skills的entities字段和actions字段。

    1. {
    2. "module": {
    3. "abilities": [
    4. {
    5. // ...
    6. "skills": [
    7. {
    8. "entities": [
    9. // ...
    10. "entity.system.default"
    11. ],
    12. "actions": [
    13. // ...
    14. "ohos.want.action.viewData"
    15. ]
    16. }
    17. ]
    18. }
    19. ]
    20. }
    21. }
  2. 在調(diào)用方want參數(shù)中的entities和action需要被包含在待匹配UIAbility的skills配置的entities和actions中。系統(tǒng)匹配到符合entities和actions參數(shù)條件的UIAbility后,會(huì)彈出選擇框展示匹配到的UIAbility實(shí)例列表供用戶選擇使用。示例中的context的獲取方式參見獲取UIAbility的Context屬性。

    1. let wantInfo = {
    2. deviceId: '', // deviceId為空表示本設(shè)備
    3. // 如果希望隱式僅在特定的捆綁包中進(jìn)行查詢,請(qǐng)取消下面的注釋。
    4. // bundleName: 'com.example.myapplication',
    5. action: 'ohos.want.action.viewData',
    6. // entities可以被省略。
    7. entities: ['entity.system.default'],
    8. }
    9. // context為調(diào)用方UIAbility的AbilityContext
    10. this.context.startAbility(wantInfo).then(() => {
    11. // ...
    12. }).catch((err) => {
    13. // ...
    14. })

    效果示意如下圖所示,點(diǎn)擊“打開PDF文檔”時(shí),會(huì)彈出選擇框供用戶選擇。

  3. 在文檔應(yīng)用使用完成之后,如需要停止當(dāng)前UIAbility實(shí)例,通過調(diào)用terminateSelf()方法實(shí)現(xiàn)。

    1. // context為需要停止的UIAbility實(shí)例的AbilityContext
    2. this.context.terminateSelf((err) => {
    3. // ...
    4. });

啟動(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é)果。

  1. 在支付應(yīng)用對(duì)應(yīng)UIAbility的module.json5配置文件中,配置skills的entities字段和actions字段。

    1. {
    2. "module": {
    3. "abilities": [
    4. {
    5. // ...
    6. "skills": [
    7. {
    8. "entities": [
    9. // ...
    10. "entity.system.default"
    11. ],
    12. "actions": [
    13. // ...
    14. "ohos.want.action.editData"
    15. ]
    16. }
    17. ]
    18. }
    19. ]
    20. }
    21. }
  2. 調(diào)用方使用startAbilityForResult()方法啟動(dòng)支付應(yīng)用的UIAbility,在調(diào)用方want參數(shù)中的entities和action需要被包含在待匹配UIAbility的skills配置的entities和actions中。異步回調(diào)中的data用于后續(xù)接收支付UIAbility停止自身后返回給調(diào)用方的信息。系統(tǒng)匹配到符合entities和actions參數(shù)條件的UIAbility后,會(huì)彈出選擇框展示匹配到的UIAbility實(shí)例列表供用戶選擇使用。

    1. let wantInfo = {
    2. deviceId: '', // deviceId為空表示本設(shè)備
    3. // uncomment line below if wish to implicitly query only in the specific bundle.
    4. // bundleName: 'com.example.myapplication',
    5. action: 'ohos.want.action.editData',
    6. // entities can be omitted.
    7. entities: ['entity.system.default'],
    8. }
    9. // context為調(diào)用方UIAbility的AbilityContext
    10. this.context.startAbilityForResult(wantInfo).then((data) => {
    11. // ...
    12. }).catch((err) => {
    13. // ...
    14. })
  3. 在支付UIAbility完成支付之后,需要調(diào)用terminateSelfWithResult()方法實(shí)現(xiàn)停止自身,并將abilityResult參數(shù)信息返回給調(diào)用方。

    1. const RESULT_CODE: number = 1001;
    2. let abilityResult = {
    3. resultCode: RESULT_CODE,
    4. want: {
    5. bundleName: 'com.example.myapplication',
    6. abilityName: 'EntryAbility',
    7. moduleName: 'entry',
    8. parameters: {
    9. payResult: 'OKay',
    10. },
    11. },
    12. }
    13. // context為被調(diào)用方UIAbility的AbilityContext
    14. this.context.terminateSelfWithResult(abilityResult, (err) => {
    15. // ...
    16. });
  4. 在調(diào)用方startAbilityForResult()方法回調(diào)中接收支付應(yīng)用返回的信息,RESULT_CODE需要與前面terminateSelfWithResult()返回的數(shù)值保持一致。

    1. const RESULT_CODE: number = 1001;
    2. let want = {
    3. // Want參數(shù)信息
    4. };
    5. // context為調(diào)用方UIAbility的AbilityContext
    6. this.context.startAbilityForResult(want).then((data) => {
    7. if (data?.resultCode === RESULT_CODE) {
    8. // 解析被調(diào)用方UIAbility返回的信息
    9. let payResult = data.want?.parameters?.payResult;
    10. // ...
    11. }
    12. }).catch((err) => {
    13. // ...
    14. })

啟動(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è)面。本文主要講解目標(biāo)UIAbility首次啟動(dòng)和目標(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è)面路徑信息,可以通過want中的parameters參數(shù)增加一個(gè)自定義參數(shù)傳遞頁(yè)面跳轉(zhuǎn)信息。示例中的context的獲取方式參見獲取UIAbility的Context屬性

  1. let wantInfo = {
  2. deviceId: '', // deviceId為空表示本設(shè)備
  3. bundleName: 'com.example.myapplication',
  4. abilityName: 'FuncAbility',
  5. moduleName: 'module1', // moduleName非必選
  6. parameters: { // 自定義參數(shù)傳遞頁(yè)面信息
  7. router: 'funcA',
  8. },
  9. }
  10. // context為調(diào)用方UIAbility的AbilityContext
  11. this.context.startAbility(wantInfo).then(() => {
  12. // ...
  13. }).catch((err) => {
  14. // ...
  15. })

目標(biāo)UIAbility首次啟動(dòng)

目標(biāo)UIAbility首次啟動(dòng)時(shí),在目標(biāo)UIAbility的onWindowStageCreate()生命周期回調(diào)中,解析EntryAbility傳遞過來(lái)的want參數(shù),獲取到需要加載的頁(yè)面信息url,傳入windowStage.loadContent()方法。

  1. import UIAbility from '@ohos.app.ability.UIAbility'
  2. import Window from '@ohos.window'
  3. export default class FuncAbility extends UIAbility {
  4. funcAbilityWant;
  5. onCreate(want, launchParam) {
  6. // 接收調(diào)用方UIAbility傳過來(lái)的參數(shù)
  7. this.funcAbilityWant = want;
  8. }
  9. onWindowStageCreate(windowStage: Window.WindowStage) {
  10. // Main window is created, set main page for this ability
  11. let url = 'pages/Index';
  12. if (this.funcAbilityWant?.parameters?.router) {
  13. if (this.funcAbilityWant.parameters.router === 'funA') {
  14. url = 'pages/Second';
  15. }
  16. }
  17. windowStage.loadContent(url, (err, data) => {
  18. // ...
  19. });
  20. }
  21. }

目標(biāo)UIAbility非首次啟動(dòng)

經(jīng)常還會(huì)遇到一類場(chǎng)景,當(dāng)應(yīng)用A已經(jīng)啟動(dòng)且處于主頁(yè)面時(shí),回到桌面,打開應(yīng)用B,并從應(yīng)用B再次啟動(dòng)應(yīng)用A,且需要跳轉(zhuǎn)到應(yīng)用A的指定頁(yè)面。例如聯(lián)系人應(yīng)用和短信應(yīng)用配合使用的場(chǎng)景。打開短信應(yīng)用主頁(yè),回到桌面,此時(shí)短信應(yīng)用處于已打開狀態(tài)且當(dāng)前處于短信應(yīng)用的主頁(yè)。再打開聯(lián)系人應(yīng)用主頁(yè),進(jìn)入聯(lián)系人用戶A查看詳情,點(diǎn)擊短信圖標(biāo),準(zhǔn)備給用戶A發(fā)送短信,此時(shí)會(huì)再次拉起短信應(yīng)用且當(dāng)前處于短信應(yīng)用的發(fā)送頁(yè)面。

針對(duì)以上場(chǎng)景,即當(dāng)應(yīng)用A的UIAbility實(shí)例已創(chuàng)建,并且處于該UIAbility實(shí)例對(duì)應(yīng)的主頁(yè)面中,此時(shí),從應(yīng)用B中需要再次啟動(dòng)應(yīng)用A的該UIAbility,并且需要跳轉(zhuǎn)到不同的頁(yè)面,這種情況下要如何實(shí)現(xiàn)呢?

  1. 在目標(biāo)UIAbility中,默認(rèn)加載的是Index頁(yè)面。由于當(dāng)前UIAbility實(shí)例之前已經(jīng)創(chuàng)建完成,此時(shí)會(huì)進(jìn)入U(xiǎn)IAbility的onNewWant()回調(diào)中且不會(huì)進(jìn)入onCreate()和onWindowStageCreate()生命周期回調(diào),在onNewWant()回調(diào)中解析調(diào)用方傳遞過來(lái)的want參數(shù),并掛在到全局變量globalThis中,以便于后續(xù)在頁(yè)面中獲取。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class FuncAbility extends UIAbility {
    3. onNewWant(want, launchParam) {
    4. // 接收調(diào)用方UIAbility傳過來(lái)的參數(shù)
    5. globalThis.funcAbilityWant = want;
    6. // ...
    7. }
    8. }
  2. 在FuncAbility中,此時(shí)需要在Index頁(yè)面中通過頁(yè)面路由Router模塊實(shí)現(xiàn)指定頁(yè)面的跳轉(zhuǎn),由于此時(shí)FuncAbility對(duì)應(yīng)的Index頁(yè)面是處于激活狀態(tài),不會(huì)重新變量聲明以及進(jìn)入aboutToAppear()生命周期回調(diào)中。因此可以在Index頁(yè)面的onPageShow()生命周期回調(diào)中實(shí)現(xiàn)頁(yè)面路由跳轉(zhuǎn)的功能。

    1. import router from '@ohos.router';
    2. @Entry
    3. @Component
    4. struct Index {
    5. onPageShow() {
    6. let funcAbilityWant = globalThis.funcAbilityWant;
    7. let url2 = funcAbilityWant?.parameters?.router;
    8. if (url2 && url2 === 'funcA') {
    9. router.replaceUrl({
    10. url: 'pages/Second',
    11. })
    12. }
    13. }
    14. // 頁(yè)面展示
    15. build() {
    16. // ...
    17. }
    18. }
說明

當(dāng)被調(diào)用方Ability的啟動(dòng)模式設(shè)置為multiton啟動(dòng)模式時(shí),每次啟動(dòng)都會(huì)創(chuàng)建一個(gè)新的實(shí)例,那么onNewWant()回調(diào)就不會(huì)被用到。

通過Call調(diào)用實(shí)現(xiàn)UIAbility交互(僅對(duì)系統(tǒng)應(yīng)用開放)

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)用開發(fā)者可通過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ì)象,通過Callee的on方法注冊(cè)回調(diào)函數(shù),當(dāng)接收到Caller發(fā)送的數(shù)據(jù)時(shí)將會(huì)調(diào)用對(duì)應(yīng)的回調(diào)函數(shù)。

說明
  1. 當(dāng)前僅支持系統(tǒng)應(yīng)用使用Call調(diào)用。

  2. CalleeAbility的啟動(dòng)模式需要為單實(shí)例。

  3. Call調(diào)用既支持本地(設(shè)備內(nèi))Call調(diào)用,也支持跨設(shè)備Call調(diào)用,下面介紹設(shè)備內(nèi)Call調(diào)用方法。

接口說明

Call功能主要接口如下表所示。具體的API詳見接口文檔。

表2 Call功能主要接口

接口名

描述

startAbilityByCall(want: Want): Promise<Caller>

啟動(dòng)指定UIAbility并獲取其Caller通信接口,默認(rèn)為后臺(tái)啟動(dòng),通過配置want可實(shí)現(xiàn)前臺(tái)啟動(dòng),詳見接口文檔。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<void>

向通用組件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è)通用組件通信斷開監(jiān)聽通知。

設(shè)備內(nèi)通過Call調(diào)用實(shí)現(xiàn)UIAbility交互,涉及如下兩部分開發(fā):

開發(fā)步驟(創(chuàng)建Callee被調(diào)用端)

在Callee被調(diào)用端,需要實(shí)現(xiàn)指定方法的數(shù)據(jù)接收回調(diào)函數(shù)、數(shù)據(jù)的序列化及反序列化方法。在需要接收數(shù)據(jù)期間,通過on接口注冊(cè)監(jiān)聽,無(wú)需接收數(shù)據(jù)時(shí)通過off接口解除監(jiān)聽。

  1. 配置Ability的啟動(dòng)模式。

    配置module.json5,將CalleeAbility配置為單實(shí)例"singleton"。

    Json字段

    字段說明

    "launchType"

    Ability的啟動(dòng)模式,設(shè)置為"singleton"類型。

    Ability配置標(biāo)簽示例如下:

    1. "abilities":[{
    2. "name": ".CalleeAbility",
    3. "srcEntrance": "./ets/CalleeAbility/CalleeAbility.ts",
    4. "launchType": "singleton",
    5. "description": "$string:CalleeAbility_desc",
    6. "icon": "$media:icon",
    7. "label": "$string:CalleeAbility_label",
    8. "visible": true
    9. }]
  2. 導(dǎo)入U(xiǎn)IAbility模塊。

    1. import Ability from '@ohos.app.ability.UIAbility';
  3. 定義約定的序列化數(shù)據(jù)。

    調(diào)用端及被調(diào)用端發(fā)送接收的數(shù)據(jù)格式需協(xié)商一致,如下示例約定數(shù)據(jù)由number和string組成。

    1. export default class MyParcelable {
    2. num: number = 0
    3. str: string = ""
    4. constructor(num, string) {
    5. this.num = num
    6. this.str = string
    7. }
    8. marshalling(messageSequence) {
    9. messageSequence.writeInt(this.num)
    10. messageSequence.writeString(this.str)
    11. return true
    12. }
    13. unmarshalling(messageSequence) {
    14. this.num = messageSequence.readInt()
    15. this.str = messageSequence.readString()
    16. return true
    17. }
    18. }
  4. 實(shí)現(xiàn)Callee.on監(jiān)聽及Callee.off解除監(jiān)聽。

    被調(diào)用端Callee的監(jiān)聽函數(shù)注冊(cè)時(shí)機(jī),取決于應(yīng)用開發(fā)者。注冊(cè)監(jiān)聽之前的數(shù)據(jù)不會(huì)被處理,取消監(jiān)聽之后的數(shù)據(jù)不會(huì)被處理。如下示例在Ability的onCreate注冊(cè)'MSG_SEND_METHOD'監(jiān)聽,在onDestroy取消監(jiān)聽,收到序列化數(shù)據(jù)后作相應(yīng)處理并返回,應(yīng)用開發(fā)者根據(jù)實(shí)際需要做相應(yīng)處理。具體示例代碼如下:

    1. const TAG: string = '[CalleeAbility]';
    2. const MSG_SEND_METHOD: string = 'CallSendMsg';
    3. function sendMsgCallback(data) {
    4. console.info('CalleeSortFunc called');
    5. // 獲取Caller發(fā)送的序列化數(shù)據(jù)
    6. let receivedData = new MyParcelable(0, '');
    7. data.readParcelable(receivedData);
    8. console.info(`receiveData[${receivedData.num}, ${receivedData.str}]`);
    9. // 作相應(yīng)處理
    10. // 返回序列化數(shù)據(jù)result給Caller
    11. return new MyParcelable(receivedData.num + 1, `send ${receivedData.str} succeed`);
    12. }
    13. export default class CalleeAbility extends Ability {
    14. onCreate(want, launchParam) {
    15. try {
    16. this.callee.on(MSG_SEND_METHOD, sendMsgCallback);
    17. } catch (error) {
    18. console.info(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`);
    19. }
    20. }
    21. onDestroy() {
    22. try {
    23. this.callee.off(MSG_SEND_METHOD);
    24. } catch (error) {
    25. console.error(TAG, `${MSG_SEND_METHOD} unregister failed with error ${JSON.stringify(error)}`);
    26. }
    27. }
    28. }

開發(fā)步驟(訪問Callee被調(diào)用端)

  1. 導(dǎo)入U(xiǎn)IAbility模塊。

    1. import Ability from '@ohos.app.ability.UIAbility';
  2. 獲取Caller通信接口。

    Ability的context屬性實(shí)現(xiàn)了startAbilityByCall方法,用于獲取指定通用組件的Caller通信接口。如下示例通過this.context獲取Ability實(shí)例的context屬性,使用startAbilityByCall拉起Callee被調(diào)用端并獲取Caller通信接口,注冊(cè)Caller的onRelease監(jiān)聽。應(yīng)用開發(fā)者根據(jù)實(shí)際需要做相應(yīng)處理。

    1. // 注冊(cè)caller的release監(jiān)聽
    2. private regOnRelease(caller) {
    3. try {
    4. caller.on("release", (msg) => {
    5. console.info(`caller onRelease is called ${msg}`);
    6. })
    7. console.info('caller register OnRelease succeed');
    8. } catch (error) {
    9. console.info(`caller register OnRelease failed with ${error}`);
    10. }
    11. }
    12. async onButtonGetCaller() {
    13. try {
    14. this.caller = await context.startAbilityByCall({
    15. bundleName: 'com.samples.CallApplication',
    16. abilityName: 'CalleeAbility'
    17. })
    18. if (this.caller === undefined) {
    19. console.info('get caller failed')
    20. return
    21. }
    22. console.info('get caller success')
    23. this.regOnRelease(this.caller)
    24. } catch (error) {
    25. console.info(`get caller failed with ${error}`)
    26. }
    27. }
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)