那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙開發:應用組件跨設備交互(流轉)【多端協同】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-06-13 10:42 ? 次閱讀

多端協同

功能描述

多端協同主要包括如下場景:

  • [通過跨設備啟動UIAbility和ServiceExtensionAbility組件實現多端協同(無返回數據)]
  • [通過跨設備啟動UIAbility組件實現多端協同(獲取返回數據)]
  • [通過跨設備連接ServiceExtensionAbility組件實現多端協同]
  • [通過跨設備Call調用實現多端協同]

多端協同流程

多端協同流程如下圖所示。

圖1 多端協同流程圖 hop-multi-device-collaboration

約束限制

  • 由于“多端協同任務管理”能力尚未具備,開發者當前只能通過開發系統應用獲取設備列表,不支持三方應用接入。
  • 多端協同需遵循[分布式跨設備組件啟動規則]。
  • 為了獲得最佳體驗,使用want傳輸的數據建議在100KB以下。
  • 開發前請熟悉鴻蒙開發指導文檔 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

通過跨設備啟動UIAbility和ServiceExtensionAbility組件實現多端協同(無返回數據)

在設備A上通過發起端應用提供的啟動按鈕,啟動設備B上指定的UIAbility與ServiceExtensionAbility。

接口說明

表1 跨設備啟動API接口功能介紹

接口名描述
startAbility(want: Want, callback: AsyncCallback): void;啟動UIAbility和ServiceExtensionAbility(callback形式)。
stopServiceExtensionAbility(want: Want, callback: AsyncCallback): void;退出啟動的ServiceExtensionAbility(callback形式)。
stopServiceExtensionAbility(want: Want): Promise;退出啟動的ServiceExtensionAbility(Promise形式)。

開發步驟

  1. 需要申請ohos.permission.DISTRIBUTED_DATASYNC權限,配置方式請參見[聲明權限]。
  2. 同時需要在應用首次啟動時彈窗向用戶申請授權,使用方式請參見[向用戶申請授權]。
  3. 獲取目標設備的設備ID。
    import hilog from '@ohos.hilog';
    import distributedDeviceManager from '@ohos.distributedDeviceManager';
    
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    let dmClass: distributedDeviceManager.DeviceManager;
    
    function initDmClass(): void {
      // 其中createDeviceManager接口為系統API
      try {
        dmClass = distributedDeviceManager.createDeviceManager('com.samples.stagemodelabilitydevelop');
        hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass) ?? '');
      } catch (err) {
        hilog.error(DOMAIN_NUMBER, TAG, 'createDeviceManager err: ' + JSON.stringify(err));
      };
    }
    
    function getRemoteDeviceId(): string | undefined {
      if (typeof dmClass === 'object' && dmClass !== null) {
        let list = dmClass.getAvailableDeviceListSync();
        hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
        if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
          return;
        }
        if (list.length === 0) {
          hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
          return;
        }
        return list[0].networkId;
      } else {
        hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
        return;
      }
    }
    
  4. 設置目標組件參數,調用[startAbility()]接口,啟動UIAbility或ServiceExtensionAbility。
    import { BusinessError } from '@ohos.base';
    import hilog from '@ohos.hilog';
    import Want from '@ohos.app.ability.Want';
    import common from '@ohos.app.ability.common';
    import distributedDeviceManager from '@ohos.distributedDeviceManager';
    import promptAction from '@ohos.promptAction';
    
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    let dmClass: distributedDeviceManager.DeviceManager;
    
    function getRemoteDeviceId(): string | undefined {
      if (typeof dmClass === 'object' && dmClass !== null) {
        let list = dmClass.getAvailableDeviceListSync();
        hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
        if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
          return;
        }
        if (list.length === 0) {
          hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
          return;
        }
        return list[0].networkId;
      } else {
        hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
        return;
      }
    };
    
    @Entry
    @Component
    struct Page_CollaborateAbility {
      private context = getContext(this) as common.UIAbilityContext;
    
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            //...
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let want: Want = {
                  deviceId: getRemoteDeviceId(),
                  bundleName: 'com.samples.stagemodelabilityinteraction',
                  abilityName: 'CollaborateAbility',
                  moduleName: 'entry' // moduleName非必選
                };
                // context為發起端UIAbility的AbilityContext
                this.context.startAbility(want).then(() = > {
                  promptAction.showToast({
                    message: $r('app.string.SuccessfulCollaboration')
                  });
                }).catch((err: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, `startAbility err: ` + JSON.stringify(err));
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    
  5. 當設備A發起端應用不需要設備B上的ServiceExtensionAbility時,可調用[stopServiceExtensionAbility]接口退出。(該接口不支持UIAbility的退出,UIAbility由用戶手動通過任務管理退出)
    import { BusinessError } from '@ohos.base';
    import hilog from '@ohos.hilog';
    import Want from '@ohos.app.ability.Want';
    import common from '@ohos.app.ability.common';
    import distributedDeviceManager from '@ohos.distributedDeviceManager';
    import promptAction from '@ohos.promptAction';
    
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    let dmClass: distributedDeviceManager.DeviceManager;
    
    function getRemoteDeviceId(): string | undefined {
      if (typeof dmClass === 'object' && dmClass !== null) {
        let list = dmClass.getAvailableDeviceListSync();
        hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
        if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
          return;
        }
        if (list.length === 0) {
          hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
          return;
        }
        return list[0].networkId;
      } else {
        hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
        return;
      }
    };
    
    @Entry
    @Component
    struct Page_CollaborateAbility {
      private context = getContext(this) as common.UIAbilityContext;
    
      build() {
        // ...
        Button('stopServiceExtensionAbility')
          .onClick(() = > {
            let want: Want = {
              deviceId: getRemoteDeviceId(),
              bundleName: 'com.example.myapplication',
              abilityName: 'FuncAbility',
              moduleName: 'module1', // moduleName非必選
            }
            // 退出由startAbility接口啟動的ServiceExtensionAbility
            this.context.stopServiceExtensionAbility(want).then(() = > {
              hilog.info(DOMAIN_NUMBER, TAG, "stop service extension ability success")
            }).catch((err: BusinessError) = > {
              hilog.error(DOMAIN_NUMBER, TAG, `stop service extension ability err is ` + JSON.stringify(err));
            })
          })
      }
    }
    

通過跨設備啟動UIAbility組件實現多端協同(獲取返回數據)

在設備A上通過應用提供的啟動按鈕,啟動設備B上指定的UIAbility,當設備B上的UIAbility退出后,會將返回值發回設備A上的發起端應用。

接口說明

表2 跨設備啟動,返回結果數據API接口功能描述

接口名描述
startAbilityForResult(want: Want, callback: AsyncCallback): void;啟動UIAbility并在該Ability退出的時候返回執行結果(callback形式)。
terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback): void;停止UIAbility,配合startAbilityForResult使用,返回給接口調用方AbilityResult信息(callback形式)。
terminateSelfWithResult(parameter: AbilityResult): Promise;停止UIAbility,配合startAbilityForResult使用,返回給接口調用方AbilityResult信息(promise形式)。

開發步驟

  1. 需要申請ohos.permission.DISTRIBUTED_DATASYNC權限,配置方式請參見[聲明權限]。
  2. 同時需要在應用首次啟動時彈窗向用戶申請授權,使用方式請參見[向用戶申請授權]。
  3. 在發起端設置目標組件參數,調用startAbilityForResult()接口啟動目標端UIAbility,異步回調中的data用于接收目標端UIAbility停止自身后返回給調用方UIAbility的信息。getRemoteDeviceId方法參照[通過跨設備啟動uiability和serviceextensionability組件實現多端協同無返回數據]。
    import { BusinessError } from '@ohos.base';
    import hilog from '@ohos.hilog';
    import Want from '@ohos.app.ability.Want';
    import common from '@ohos.app.ability.common';
    import distributedDeviceManager from '@ohos.distributedDeviceManager';
    import promptAction from '@ohos.promptAction';
    
    const DOMAIN_NUMBER: number = 0xFF00;
    const TAG: string = '[Page_CollaborateAbility]';
    let dmClass: distributedDeviceManager.DeviceManager;
    
    function getRemoteDeviceId(): string | undefined {
      if (typeof dmClass === 'object' && dmClass !== null) {
        let list = dmClass.getAvailableDeviceListSync();
        hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
        if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
          return;
        }
        if (list.length === 0) {
          hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
          return;
        }
        return list[0].networkId;
      } else {
        hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
        return;
      }
    };
    
    @Entry
    @Component
    struct Page_CollaborateAbility {
      private context = getContext(this) as common.UIAbilityContext;
    
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            //...
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let want: Want = {
                  deviceId: getRemoteDeviceId(),
                  bundleName: 'com.samples.stagemodelabilityinteraction',
                  abilityName: 'ServiceExtAbility',
                  moduleName: 'entry' // moduleName非必選
                };
                // 退出由startAbility接口啟動的ServiceExtensionAbility
                this.context.stopServiceExtensionAbility(want).then(() = > {
                  hilog.info(DOMAIN_NUMBER, TAG, 'stop service extension ability success')
                  promptAction.showToast({
                    message: $r('app.string.SuccessfullyStop')
                  });
                }).catch((err: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, `stop service extension ability err is ` + JSON.stringify(err));
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    
  4. 在目標端UIAbility任務完成后,調用terminateSelfWithResult()方法,將數據返回給發起端的UIAbility。
    import common from '@ohos.app.ability.common';
    import hilog from '@ohos.hilog';
    import { BusinessError } from '@ohos.base';
    
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Entry
    @Component
    struct Page_CollaborateAbility {
      private context = getContext(this) as common.UIAbilityContext;
    
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            //...
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                const RESULT_CODE: number = 1001;
                // context為目標端UIAbility的AbilityContext
                this.context.terminateSelfWithResult(
                  {
                    resultCode: RESULT_CODE,
                    want: {
                      bundleName: 'ohos.samples.stagemodelabilitydevelop',
                      abilityName: 'CollaborateAbility',
                      moduleName: 'entry',
                      parameters: {
                        info: '來自Page_CollaborateAbility頁面'
                      }
                    }
                  },
                  (err: BusinessError) = > {
                    hilog.info(DOMAIN_NUMBER, TAG, `terminateSelfWithResult err: ` + JSON.stringify(err));
                  });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    
  5. 發起端UIAbility接收到目標端UIAbility返回的信息,對其進行處理。
    import { BusinessError } from '@ohos.base';
    import hilog from '@ohos.hilog';
    import Want from '@ohos.app.ability.Want';
    import common from '@ohos.app.ability.common';
    import distributedDeviceManager from '@ohos.distributedDeviceManager';
    import promptAction from '@ohos.promptAction';
    
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    let dmClass: distributedDeviceManager.DeviceManager;
    
    function getRemoteDeviceId(): string | undefined {
      if (typeof dmClass === 'object' && dmClass !== null) {
        let list = dmClass.getAvailableDeviceListSync();
        hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
        if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
          return;
        }
        if (list.length === 0) {
          hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
          return;
        }
        return list[0].networkId;
      } else {
        hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
        return;
      }
    };
    
    @Entry
    @Component
    struct Page_CollaborateAbility {
      private context = getContext(this) as common.UIAbilityContext;
    
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            //...
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let want: Want = {
                  deviceId: getRemoteDeviceId(),
                  bundleName: 'com.samples.stagemodelabilityinteraction',
                  abilityName: 'CollaborateAbility',
                  moduleName: 'entry' // moduleName非必選
                };
                const RESULT_CODE: number = 1001;
                // context為調用方UIAbility的UIAbilityContext
                this.context.startAbilityForResult(want).then((data) = > {
                  if (data?.resultCode === RESULT_CODE) {
                    // 解析目標端UIAbility返回的信息
                    let info = data.want?.parameters?.info;
                    hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? '');
                    if (info !== null) {
                      promptAction.showToast({
                        message : JSON.stringify(info)
                      });
                    }
                  }
                }).catch((error: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, `startAbilityForResult err: ` + JSON.stringify(error));
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    

通過跨設備連接ServiceExtensionAbility組件實現多端協同

系統應用可以通過[connectServiceExtensionAbility()]跨設備連接一個服務,實現跨設備遠程調用。比如:分布式游戲場景,平板作為遙控器,智慧屏作為顯示器。

接口說明

表3 跨設備連接API接口功能介紹

接口名描述
connectServiceExtensionAbility(want: Want, options: ConnectOptions): number;連接ServiceExtensionAbility。
disconnectServiceExtensionAbility(connection: number, callback:AsyncCallback): void;斷開連接(callback形式)。
disconnectServiceExtensionAbility(connection: number): Promise;斷開連接(promise形式)。

開發步驟

  1. 需要申請ohos.permission.DISTRIBUTED_DATASYNC權限,配置方式請參見[聲明權限]。
  2. 同時需要在應用首次啟動時彈窗向用戶申請授權,使用方式請參見[向用戶申請授權]。
  3. 如果已有后臺服務,請直接進入下一步;如果沒有,則[實現一個后臺服務(僅對系統應用開放)]。
  4. 連接一個后臺服務。
    • 實現IAbilityConnection接口。IAbilityConnection提供了以下方法供開發者實現:onConnect()是用來處理連接Service成功的回調,onDisconnect()是用來處理Service異常終止的回調,onFailed()是用來處理連接Service失敗的回調。

    • 設置目標組件參數,包括目標設備ID、Bundle名稱、Ability名稱。

    • 調用connectServiceExtensionAbility發起連接。

    • 連接成功,收到目標設備返回的服務句柄。

    • 進行跨設備調用,獲得目標端服務返回的結果。

      import { BusinessError } from '@ohos.base';
      import hilog from '@ohos.hilog';
      import Want from '@ohos.app.ability.Want';
      import common from '@ohos.app.ability.common';
      import distributedDeviceManager from '@ohos.distributedDeviceManager';
      import rpc from '@ohos.rpc';
      
      const TAG: string = '[Page_CollaborateAbility]';
      const DOMAIN_NUMBER: number = 0xFF00;
      const REQUEST_CODE = 1;
      let dmClass: distributedDeviceManager.DeviceManager;
      let connectionId: number;
      let options: common.ConnectOptions = {
        onConnect(elementName, remote): void {
          hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');
          if (remote === null) {
            hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`);
            return;
          }
          let option = new rpc.MessageOption();
          let data = new rpc.MessageSequence();
          let reply = new rpc.MessageSequence();
          data.writeInt(99); // 開發者可發送data到目標端應用進行相應操作
          // @param code 表示客戶端發送的服務請求代碼。
          // @param data 表示客戶端發送的{@link MessageSequence}對象。
          // @param reply 表示遠程服務發送的響應消息對象。
          // @param options 指示操作是同步的還是異步的。
          //
          // @return 如果操作成功返回{@code true}; 否則返回 {@code false}。
          remote.sendMessageRequest(REQUEST_CODE, data, reply, option).then((ret: rpc.RequestResult) = > {
            let errCode = reply.readInt(); // 在成功連接的情況下,會收到來自目標端返回的信息(100)
            let msg: number = 0;
            if (errCode === 0) {
              msg = reply.readInt();
            }
        // 成功連接后臺服務
            hilog.info(DOMAIN_NUMBER, TAG, `sendRequest msg:${msg}`);
          }).catch((error: BusinessError) = > {
            hilog.info(DOMAIN_NUMBER, TAG, `sendRequest failed, ${JSON.stringify(error)}`);
          });
        },
        onDisconnect(elementName): void {
          hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');
        },
        onFailed(code) void {
          hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback');
        }
      };
      
      function getRemoteDeviceId(): string | undefined {
        if (typeof dmClass === 'object' && dmClass !== null) {
          let list = dmClass.getAvailableDeviceListSync();
          hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
          if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
            hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
            return;
          }
          if (list.length === 0) {
            hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
            return;
          }
          return list[0].networkId;
        } else {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
          return;
        }
      }
      
      @Entry
      @Component
      struct Page_CollaborateAbility {
        private context = getContext(this) as common.UIAbilityContext;
        build() {
          Column() {
            //...
            List({ initialIndex: 0 }) {
              //...
              ListItem() {
                Row() {
                  //...
                }
                .onClick(() = > {
                  let want: Want = {
                    'deviceId': getRemoteDeviceId(),
                    'bundleName': 'com.samples.stagemodelabilityinteraction',
                    'abilityName': 'ServiceExtAbility'
                  };
                  // 建立連接后返回的Id需要保存下來,在解綁服務時需要作為參數傳入
                  connectionId = this.context.connectServiceExtensionAbility(want, options);
                })
              }
              //...
            }
            //...
          }
          //...
        }
      }
      

      getRemoteDeviceId方法參照[通過跨設備啟動uiability和serviceextensionability組件實現多端協同無返回數據]。

  5. 斷開連接。調用disconnectServiceExtensionAbility()斷開與后臺服務的連接。
    import { BusinessError } from '@ohos.base';
    import hilog from '@ohos.hilog';
    import Want from '@ohos.app.ability.Want';
    import common from '@ohos.app.ability.common';
    import rpc from '@ohos.rpc';
    import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy';
    import promptAction from '@ohos.promptAction';
    
    let connectionId: number;
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Entry
    @Component
    struct Page_CollaborateAbility {
      private context = getContext(this) as common.UIAbilityContext;
    
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            //...
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                this.context.disconnectServiceExtensionAbility(connectionId).then(() = > {
                  hilog.info(DOMAIN_NUMBER, TAG, 'disconnectServiceExtensionAbility success');
                  // 成功斷連后臺服務
                  promptAction.showToast({
                    message: $r('app.string.SuccessfullyDisconnectBackendService')
                  })
                }).catch((error: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, 'disconnectServiceExtensionAbility failed');
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    

通過跨設備Call調用實現多端協同

跨設備Call調用的基本原理與設備內Call調用相同,請參見[通過Call調用實現UIAbility交互(僅對系統應用開放)]。

下面介紹跨設備Call調用實現多端協同的方法。

接口說明

表4 Call API接口功能介紹

接口名描述
startAbilityByCall(want: Want): Promise;啟動指定UIAbility至前臺或后臺,同時獲取其Caller通信接口,調用方可使用Caller與被啟動的Ability進行通信
on(method: string, callback: CalleeCallBack): void通用組件Callee注冊method對應的callback方法。
off(method: string): void通用組件Callee解注冊method的callback方法。
call(method: string, data: rpc.Parcelable): Promise向通用組件Callee發送約定序列化數據。
callWithResult(method: string, data: rpc.Parcelable): Promise向通用組件Callee發送約定序列化數據, 并將Callee返回的約定序列化數據帶回。
release(): void釋放通用組件的Caller通信接口。
on(type: "release", callback: OnReleaseCallback): void注冊通用組件通信斷開監聽通知。

開發步驟

  1. 需要申請ohos.permission.DISTRIBUTED_DATASYNC權限,配置方式請參見[聲明權限]。
  2. 同時需要在應用首次啟動時彈窗向用戶申請授權,使用方式請參見[向用戶申請授權]。
  3. 創建被調用端UIAbility。 被調用端UIAbility需要實現指定方法的數據接收回調函數、數據的序列化及反序列化方法。在需要接收數據期間,通過on接口注冊監聽,無需接收數據時通過off接口解除監聽。
    1. 配置UIAbility的啟動模式。 配置module.json5,將CalleeAbility配置為單實例"singleton"。

      Json字段字段說明
      “launchType”Ability的啟動模式,設置為"singleton"類型。

      UIAbility配置標簽示例如下:

      "abilities":[{
          "name": ".CalleeAbility",
          "srcEntry": "./ets/CalleeAbility/CalleeAbility.ts",
          "launchType": "singleton",
          "description": "$string:CalleeAbility_desc",
          "icon": "$media:icon",
          "label": "$string:CalleeAbility_label",
          "exported": true
      }]
      
    2. 導入UIAbility模塊。

      import UIAbility from '@ohos.app.ability.UIAbility';
      
    3. 定義約定的序列化數據。 調用端及被調用端發送接收的數據格式需協商一致,如下示例約定數據由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: number, string: 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;
        };
      };
      
    4. 實現Callee.on監聽及Callee.off解除監聽。 如下示例在Ability的onCreate注冊MSG_SEND_METHOD監聽,在onDestroy取消監聽,收到序列化數據后作相應處理并返回。應用開發者根據實際業務需要做相應處理。

      import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
      import UIAbility from '@ohos.app.ability.UIAbility';
      import type Want from '@ohos.app.ability.Want';
      import type { Caller } from '@ohos.app.ability.UIAbility';
      import hilog from '@ohos.hilog';
      import type rpc from '@ohos.rpc';
      
      
      const TAG: string = '[CalleeAbility]';
      const MSG_SEND_METHOD: string = 'CallSendMsg';
      const DOMAIN_NUMBER: number = 0xFF00;
      
      class MyParcelable {
        num: number = 0;
        str: string = '';
      
        constructor(num: number, string: string) {
          this.num = num;
          this.str = string;
        };
      
        mySequenceable(num: number, string: 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發送的序列化數據
        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;
      
        // 作相應處理
        // 返回序列化數據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;
            }
            hilog.info(DOMAIN_NUMBER, TAG, 'caller release succeed');
          } catch (error) {
            hilog.info(DOMAIN_NUMBER, TAG, `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}`);
          };
        };
      };
      
  4. 獲取Caller接口,訪問被調用端UIAbility。
    1. 導入UIAbility模塊。

      import UIAbility from '@ohos.app.ability.UIAbility';
      
    2. 獲取Caller通信接口。 Ability的context屬性實現了startAbilityByCall方法,用于獲取指定通用組件的Caller通信接口。如下示例通過this.context獲取Ability實例的context屬性,使用startAbilityByCall拉起Callee被調用端并獲取Caller通信接口,注冊Caller的onRelease和onRemoteStateChange監聽。應用開發者根據實際業務需要做相應處理。

      import { BusinessError } from '@ohos.base';
      import { Caller } from '@ohos.app.ability.UIAbility';
      import common from '@ohos.app.ability.common';
      import hilog from '@ohos.hilog';
      import distributedDeviceManager from '@ohos.distributedDeviceManager';
      
      const TAG: string = '[Page_CollaborateAbility]';
      const DOMAIN_NUMBER: number = 0xFF00;
      let caller: Caller | undefined;
      let dmClass: distributedDeviceManager.DeviceManager;
      
      function getRemoteDeviceId(): string | undefined {
        if (typeof dmClass === 'object' && dmClass !== null) {
          let list = dmClass.getAvailableDeviceListSync();
          hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(dmClass), JSON.stringify(list));
          if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
            hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: list is null');
            return;
          }
          if (list.length === 0) {
            hilog.info(DOMAIN_NUMBER, TAG, `getRemoteDeviceId err: list is empty`);
            return;
          }
          return list[0].networkId;
        } else {
          hilog.info(DOMAIN_NUMBER, TAG, 'getRemoteDeviceId err: dmClass is null');
          return;
        }
      };
      
      @Entry
      @Component
      struct Page_CollaborateAbility {
        private context = getContext(this) as common.UIAbilityContext;
      
        build() {
          Column() {
            //...
            List({ initialIndex: 0 }) {
              //...
              ListItem() {
                Row() {
                  //...
                }
                .onClick(() = > {
                  let caller: Caller | undefined;
                  let context = this.context;
      
                  context.startAbilityByCall({
                    deviceId: getRemoteDeviceId(),
                    bundleName: 'com.samples.stagemodelabilityinteraction',
                    abilityName: 'CalleeAbility'
                  }).then((data) = > {
                    if (data !== null) {
                      caller = data;
                      hilog.info(DOMAIN_NUMBER, TAG, 'get remote caller success');
                      // 注冊caller的release監聽
                      caller.onRelease((msg) = > {
                        hilog.info(DOMAIN_NUMBER, TAG, `remote caller onRelease is called ${msg}`);
                      });
                      hilog.info(DOMAIN_NUMBER, TAG, 'remote caller register OnRelease succeed');
                      promptAction.showToast({
                        message: $r('app.string.CallerSuccess')
                      });
                      // 注冊caller的協同場景下跨設備組件狀態變化監聽通知
                      try {
                        caller.onRemoteStateChange((str) = > {
                          hilog.info(DOMAIN_NUMBER, TAG, 'Remote state changed ' + str);
                        });
                      } catch (error) {
                        hilog.info(DOMAIN_NUMBER, TAG, `Caller.onRemoteStateChange catch error, error.code: ${JSON.stringify(error.code)}, error.message: ${JSON.stringify(error.message)}`);
                      };
                    }
                  }).catch((error: BusinessError) = > {
                    hilog.error(DOMAIN_NUMBER, TAG, `get remote caller failed with ${error}`);
                  });
                })
              }
              //...
            }
            //...
          }
          //...
        }
      }
      

      getRemoteDeviceId方法參照[通過跨設備啟動uiability和serviceextensionability組件實現多端協同無返回數據]。

  5. 向被調用端UIAbility發送約定序列化數據。
    1. 向被調用端發送Parcelable數據有兩種方式,一種是不帶返回值,一種是獲取被調用端返回的數據,method以及序列化數據需要與被調用端協商一致。如下示例調用Call接口,向Callee被調用端發送數據。

      import UIAbility from '@ohos.app.ability.UIAbility';
      import type { Caller } from '@ohos.app.ability.UIAbility';
      import type rpc from '@ohos.rpc';
      import hilog from '@ohos.hilog';
      
      const TAG: string = '[CalleeAbility]';
      const DOMAIN_NUMBER: number = 0xFF00;
      const MSG_SEND_METHOD: string = 'CallSendMsg';
      class MyParcelable {
        num: number = 0;
        str: string = '';
      
        constructor(num: number, string: string) {
          this.num = num;
          this.str = string;
        };
      
        mySequenceable(num: number, string: 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;
        };
      };
      
      export default class EntryAbility extends UIAbility {
        // ...
        caller: Caller | undefined;
        async onButtonCall(): Promise< void > {
          try {
            let msg: MyParcelable = new MyParcelable(1, 'origin_Msg');
            if (this.caller) {
              await this.caller.call(MSG_SEND_METHOD, msg);
            }
          } catch (error) {
            hilog.info(DOMAIN_NUMBER, TAG, `caller call failed with ${error}`);
          };
        }
        // ...
      }
      
    2. 如下示例調用CallWithResult接口,向Callee被調用端發送待處理的數據originMsg,并將’CallSendMsg’方法處理完畢的數據賦值給backMsg。

      import UIAbility from '@ohos.app.ability.UIAbility';
      import type { Caller } from '@ohos.app.ability.UIAbility';
      import type rpc from '@ohos.rpc';
      import hilog from '@ohos.hilog';
      
      const TAG: string = '[CalleeAbility]';
      const DOMAIN_NUMBER: number = 0xFF00;
      
      const MSG_SEND_METHOD: string = 'CallSendMsg';
      let originMsg: string = '';
      let backMsg: string = '';
      
      class MyParcelable {
        num: number = 0;
        str: string = '';
      
        constructor(num: number, string: string) {
          this.num = num;
          this.str = string;
        };
      
        mySequenceable(num: number, string: 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;
        };
      };
      
      export default class EntryAbility extends UIAbility {
        // ...
        caller: Caller | undefined;
        async onButtonCallWithResult(originMsg: string, backMsg: string): Promise< void > {
          try {
            let msg: MyParcelable = new MyParcelable(1, originMsg);
            if (this.caller) {
              const data = await this.caller.callWithResult(MSG_SEND_METHOD, msg);
              hilog.info(DOMAIN_NUMBER, TAG, 'caller callWithResult succeed');
              let result: MyParcelable = new MyParcelable(0, '');
              data.readParcelable(result);
              backMsg = result.str;
              hilog.info(DOMAIN_NUMBER, TAG, `caller result is [${result.num}, ${result.str}]`);
            }
          } catch (error) {
            hilog.info(DOMAIN_NUMBER, TAG, `caller callWithResult failed with ${error}`);
          };
        }
        // ...
      }
      
      `HarmonyOSOpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
      

      搜狗高速瀏覽器截圖20240326151450.png

  6. 釋放Caller通信接口。 Caller不再使用后,應用開發者可以通過release接口釋放Caller。
    import UIAbility from '@ohos.app.ability.UIAbility';
    import type { Caller } from '@ohos.app.ability.UIAbility';
    import hilog from '@ohos.hilog';
    
    export default class EntryAbility extends UIAbility {
      caller: Caller | undefined;
      releaseCall(): void {
        try {
          if (this.caller) {
            this.caller.release();
            this.caller = undefined;
          }
          hilog.info(DOMAIN_NUMBER, TAG, 'caller release succeed');
        } catch (error) {
          hilog.info(DOMAIN_NUMBER, TAG, `caller release failed with ${error}`);
        };
      }
    }
    

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 組件
    +關注

    關注

    1

    文章

    518

    瀏覽量

    17926
  • 鴻蒙
    +關注

    關注

    57

    文章

    2392

    瀏覽量

    43059
收藏 人收藏

    評論

    相關推薦

    新能力讓數據多端協同更便捷,數據端遷移更高效

    分布式數據管理平臺新增變量和文件的全局訪問框架,以及文件分享框架,幫助開發者更便捷地實現數據的“多端協同”,更高效地實現數據的“端遷移”。這些新能力將在HarmonyOS的新版本中體
    的頭像 發表于 01-12 16:07 ?4925次閱讀
    新能力讓數據<b class='flag-5'>多端</b><b class='flag-5'>協同</b>更便捷,數據<b class='flag-5'>跨</b>端遷移更高效

    鴻蒙千帆起】《開心消消樂》完成鴻蒙原生應用開發,創新多端聯動用戶體驗

    更優質的用戶體驗,基于強大的 AI 能力還可以實現精準識別、精確投放,為伙伴提供新流量,并共享全場景服務分發,助力生態共贏。數據顯示,截至今年 8 月份,鴻蒙生態的設備數已超過 7 億,鴻蒙生態
    發表于 01-03 10:22

    HarmonyOS NEXT Developer Beta1最新術語表

    郵件設備編輯、多設備協同健身、多屏游戲等分布式業務。 流轉開發者提供更廣的使用場景和更新的產
    發表于 06-27 16:16

    為滿足全場景智慧體驗 鴻蒙系統一四大技術特性!

    ,分布式架構Kit提供屏幕布局控件以及交互的自動適配,支持控件拖拽,面向預覽的可視化編程,從而使開發者可以基于同一工程高效構建多端自動運行App,實現真正的一次開發
    發表于 09-03 21:09

    HarmonyOS學習之八:鴻蒙系統從1.0到2.0的提升

    協同優化,將搭載于音箱、耳機等產品。今年,HarmonyOS2.0 進行了全新定義,即全面使能全場景生態,包括設備、服務流轉、極速直達、語音視頻、隱私安全五個方面能力。 通過
    發表于 11-27 09:40

    華為鴻蒙系統 HarmonyOS 2.0 京東、美團、優酷等軟件,分布式設備交互演示及簡單說明

    華為鴻蒙系統 HarmonyOS 2.0京東、美團、優酷等軟件,分布式設備交互演示及簡單說明
    發表于 01-14 09:52

    HarmonyOS應用框架如何解決多設備交互問題?

    應用框架中提供了兩種基礎功能,分別是:多端協同端遷移。接下來我們將介紹HarmonyOS的上述兩個能力是如何解決多設備交互問題的。二、H
    發表于 08-12 11:03

    HarmonyOS原子化服務卡片開發-分布式體驗學習

    1.原子化服務流轉在HarmonyOS中泛指涉及多端的分布式操作。流轉能力打破設備界限,多設備聯動,使用戶應用程序可分可合、可
    發表于 09-07 09:38

    HDC2021技術分論壇:廣發證券攜手HarmonyOS打造智慧金融服務

    ,點擊確認后,即可將手機中自選股票同步流轉至手表,整體流程便捷流暢。圖4 協同豐富的服務卡片和終端的互聯互通,組成一個虛擬的超級終端,將人、
    發表于 11-23 17:02

    新能力讓數據多端協同更便捷,數據端遷移更高效!

    文檔演示場景中,文檔演示狀態(比如翻頁、頁面放大、頁面縮小和涂鴉等)其實就是變量。如果這些變量支持“全局”訪問,那么開發設備訪問這些變量就能像操作本地變量一樣,數據就能夠自動高效、便捷地
    發表于 01-11 10:41

    DevEco Studio 2.1平臺設備交互使用示例

    DevEco Studio 2.1新增開發者使用的平臺設備交互界面(超級用戶可以使用該設備
    發表于 03-31 15:02

    OpenHarmony應用模型的構成要素與Stage優勢

    ,便捷實現端遷移。 在多端協同場景下,應用組件具備組件間通信的RPC調用能力,天然支持
    發表于 09-26 16:48

    華為發布HarmonyOS2,全新桌面支持應用設備流轉

    華為正式發布了HarmonyOS 2,鴻蒙系統新亮點先知道,不僅有全新桌面,還支持應用設備流轉,新奇玩法你值得期待。
    的頭像 發表于 06-02 20:43 ?1.1w次閱讀

    鴻蒙開發:應用組件設備交互流轉)【概述】

    隨著全場景多設備的生活方式不斷深入,用戶擁有的設備越來越多,不同設備都能在適合的場景下提供良好的體驗,例如手表可以提供及時的信息查看能力,電視可以帶來沉浸的觀影體驗。但是,每個設備也有
    的頭像 發表于 06-11 15:40 ?807次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:應用<b class='flag-5'>組件</b><b class='flag-5'>跨</b><b class='flag-5'>設備</b><b class='flag-5'>交互</b>(<b class='flag-5'>流轉</b>)【概述】

    鴻蒙開發:應用組件設備交互流轉)【端遷移】

    端遷移的核心任務是將應用的當前狀態(包括頁面控件、狀態變量等)無縫遷移到另一設備,從而在新設備上無縫接續應用體驗。這意味著用戶在一臺設備上進行的操作可以在另一臺
    的頭像 發表于 06-11 17:10 ?1380次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:應用<b class='flag-5'>組件</b><b class='flag-5'>跨</b><b class='flag-5'>設備</b><b class='flag-5'>交互</b>(<b class='flag-5'>流轉</b>)【<b class='flag-5'>跨</b>端遷移】
    KK百家乐官网娱乐城| 百家乐官网庄闲下载| 百家乐投注网出租| 百家乐类游戏网站| 有破解百家乐官网仪器| 大发888真人新浪微群| 81数理 做生意| 百家乐官网网上投注作弊| 大发888 casino| 百家乐门户网站| 百家乐官网游戏什么时间容易出对| 汇丰娱乐城| 大发888投注大发娱乐| 顶尖百家乐学习| 永利百家乐官网娱乐平台| 利博国际网址| 百家乐手机壳| 澳门百家乐破解方法| 百家乐官网赌场公司| 网络棋牌室| 百家乐赌博博彩赌博网| 做生意的门的方向| 百家乐官网科学| 博九网百家乐官网游戏| 赌场回忆录| 元游视频棋牌游戏| 百家乐庄最高连开几把| 太阳城百家乐筹码租| 豪享博百家乐官网的玩法技巧和规则| 常熟市| 足球即时比分| 二八杠技术| 金冠百家乐的玩法技巧和规则| 立博百家乐游戏| 博之道百家乐官网的玩法技巧和规则| 百家乐官网破解视频| 大发888下载17| 百家乐筹码皇冠| 木棉百家乐网络| 百家乐實戰後二穩賺| 百家乐tt娱乐城|