色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

鴻蒙Ability Kit(程序框架服務)【ServiceExtensionAbility】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-06-04 14:50 ? 次閱讀

ServiceExtensionAbility

概述

[ServiceExtensionAbility]是SERVICE類型的ExtensionAbility組件,提供后臺服務能力,其內部持有了一個[ServiceExtensionContext],通過[ServiceExtensionContext]提供了豐富的接口供外部使用。

本文描述中稱被啟動的ServiceExtensionAbility為服務端,稱啟動ServiceExtensionAbility的組件為客戶端。

[ServiceExtensionAbility]可以被其他組件啟動或連接,并根據調用者的請求信息在后臺處理相關事務。[ServiceExtensionAbility]支持以啟動和連接兩種形式運行,系統應用可以調用[startServiceExtensionAbility()]方法啟動后臺服務,也可以調用[connectServiceExtensionAbility()]方法連接后臺服務,而三方應用只能調用[connectServiceExtensionAbility()]方法連接后臺服務。啟動和連接后臺服務的差別:

  • 啟動 :AbilityA啟動ServiceB,啟動后AbilityA和ServiceB為弱關聯,AbilityA退出后,ServiceB可以繼續存在。
  • 連接 :AbilityA連接ServiceB,連接后AbilityA和ServiceB為強關聯,AbilityA退出后,ServiceB也一起退出。

此處有如下細節需要注意:

  • 若Service只通過connect的方式被拉起,那么該Service的生命周期將受客戶端控制,當客戶端調用一次[connectServiceExtensionAbility()]方法,將建立一個連接,當客戶端退出或者調用[disconnectServiceExtensionAbility()]方法,該連接將斷開。當所有連接都斷開后,Service將自動退出。
  • Service一旦通過start的方式被拉起,將不會自動退出,系統應用可以調用[stopServiceExtensionAbility()]方法將Service退出。
  • 只能在主線程線程中執行connect/disconnect操作,不要在Worker、TaskPool等子線程中執行connect/disconnect操作。

說明:
開發前請熟悉鴻蒙開發指導文檔gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md點擊或者復制轉到。

  1. 當前不支持三方應用實現ServiceExtensionAbility。如果三方開發者想要實現后臺處理相關事務的功能,可以使用后臺任務,具體請參見[后臺任務]。
  2. 三方應用的UIAbility組件可以通過Context連接系統提供的ServiceExtensionAbility。
  3. 三方應用需要在前臺獲焦的情況下才能連接系統提供的ServiceExtensionAbility。
    搜狗高速瀏覽器截圖20240326151450.png

生命周期

[ServiceExtensionAbility]提供了onCreate()、onRequest()、onConnect()、onDisconnect()和onDestroy()生命周期回調,根據需要重寫對應的回調方法。下圖展示了ServiceExtensionAbility的生命周期。

圖1 ServiceExtensionAbility生命周期
ServiceExtensionAbility-lifecycle

  • onCreate 服務被首次創建時觸發該回調,開發者可以在此進行一些初始化的操作,例如注冊公共事件監聽等。

    說明: 如果服務已創建,再次啟動該ServiceExtensionAbility不會觸發onCreate()回調。

  • onRequest 當另一個組件調用[startServiceExtensionAbility()]方法啟動該服務組件時,觸發該回調。執行此方法后,服務會啟動并在后臺運行。每調用一次[startServiceExtensionAbility()]方法均會觸發該回調。
  • onConnect 當另一個組件調用[connectServiceExtensionAbility()]方法與該服務連接時,觸發該回調。開發者在此方法中,返回一個遠端代理對象(IRemoteObject),客戶端拿到這個對象后可以通過這個對象與服務端進行RPC通信,同時系統側也會將該遠端代理對象(IRemoteObject)儲存。后續若有組件再調用[connectServiceExtensionAbility()]方法,系統側會直接將所保存的遠端代理對象(IRemoteObject)返回,而不再觸發該回調。
  • onDisconnect 當最后一個連接斷開時,將觸發該回調。客戶端死亡或者調用[disconnectServiceExtensionAbility()]方法可以使連接斷開。
  • onDestroy 當不再使用服務且準備將其銷毀該實例時,觸發該回調。開發者可以在該回調中清理資源,如注銷監聽等。

實現一個后臺服務(僅對系統應用開放)

開發準備

只有系統應用才允許實現ServiceExtensionAbility,因此開發者在開發之前需做如下準備:

  • 替換Full SDK :ServiceExtensionAbility相關接口都被標記為System-API,默認對開發者隱藏,因此需要手動從鏡像站點獲取Full SDK,并在DevEco Studio中替換,具體操作可參考[替換指南]。
  • 申請AllowAppUsePrivilegeExtension特權 :只有具有AllowAppUsePrivilegeExtension特權的應用才允許開發ServiceExtensionAbility,具體申請方式可參考[應用特權配置指南])。

定義IDL接口

ServiceExtensionAbility作為后臺服務,需要向外部提供可調用的接口,開發者可將接口定義在idl文件中,并使用[IDL工具]生成對應的proxy、stub文件。此處定義一個名為IIdlServiceExt.idl的文件作為示例:

interface OHOS.IIdlServiceExt {
  int ProcessData([in] int data);
  void InsertDataToMap([in] String key, [in] int val);
}

在DevEco Studio工程Module對應的ets目錄下手動新建名為IdlServiceExt的目錄,將[IDL工具]生成的文件復制到該目錄下,并創建一個名為idl_service_ext_impl.ts的文件,作為idl接口的實現:

├── ets
│ ├── IdlServiceExt
│ │   ├── i_idl_service_ext.ts      # 生成文件
│ │   ├── idl_service_ext_proxy.ts  # 生成文件
│ │   ├── idl_service_ext_stub.ts   # 生成文件
│ │   ├── idl_service_ext_impl.ts   # 開發者自定義文件,對idl接口的具體實現
│ └
└

idl_service_ext_impl.ts實現如下:

import IdlServiceExtStub from './idl_service_ext_stub';
import hilog from '@ohos.hilog';
import type { insertDataToMapCallback } from './i_idl_service_ext';
import type { processDataCallback } from './i_idl_service_ext';

const ERR_OK = 0;
const TAG: string = "[IdlServiceExtImpl]";
const DOMAIN_NUMBER: number = 0xFF00;

// 開發者需要在這個類型里對接口進行實現
export default class ServiceExtImpl extends IdlServiceExtStub {
  processData(data: number, callback: processDataCallback): void {
    // 開發者自行實現業務邏輯
    hilog.info(DOMAIN_NUMBER, TAG, `processData: ${data}`);
    callback(ERR_OK, data + 1); // 鑒權通過,執行正常業務邏輯
  }

  insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void {
    // 開發者自行實現業務邏輯
    hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, key: ${key}  val: ${val}`);
    callback(ERR_OK);
  }
}

創建ServiceExtensionAbility

在DevEco Studio工程中手動新建一個ServiceExtensionAbility,具體步驟如下:

  1. 在工程Module對應的ets目錄下,右鍵選擇“New > Directory”,新建一個目錄并命名為ServiceExtAbility。
  2. 在ServiceExtAbility目錄,右鍵選擇“New > ArkTS File”,新建一個文件并命名為ServiceExtAbility.ets。
    ├── ets
    │ ├── IdlServiceExt
    │ │   ├── i_idl_service_ext.ets      # 生成文件
    │ │   ├── idl_service_ext_proxy.ets  # 生成文件
    │ │   ├── idl_service_ext_stub.ets   # 生成文件
    │ │   ├── idl_service_ext_impl.ets   # 開發者自定義文件,對idl接口的具體實現
    │ ├── ServiceExtAbility
    │ │   ├── ServiceExtAbility.ets
    └
    
  3. 在ServiceExtAbility.ets文件中,增加導入ServiceExtensionAbility的依賴包,自定義類繼承ServiceExtensionAbility并實現生命周期回調,在onConnect生命周期回調里,需要將之前定義的ServiceExtImpl對象返回。
    import hilog from '@ohos.hilog';
    import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
    import ServiceExtImpl from '../IdlServiceExt/idl_service_ext_impl';
    import type Want from '@ohos.app.ability.Want';
    import type rpc from '@ohos.rpc';
    
    const TAG: string = '[ServiceExtAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    export default class ServiceExtAbility extends ServiceExtensionAbility {
      serviceExtImpl: ServiceExtImpl = new ServiceExtImpl('ExtImpl');
    
      onCreate(want: Want): void {
        let serviceExtensionContext = this.context;
        hilog.info(DOMAIN_NUMBER, TAG, `onCreate, want: ${want.abilityName}`);
      };
    
      onRequest(want: Want, startId: number): void {
        hilog.info(DOMAIN_NUMBER, TAG, `onRequest, want: ${want.abilityName}`);
      };
    
      onConnect(want: Want): rpc.RemoteObject {
        hilog.info(DOMAIN_NUMBER, TAG, `onConnect, want: ${want.abilityName}`);
        // 返回ServiceExtImpl對象,客戶端獲取后便可以與ServiceExtensionAbility進行通信
        return this.serviceExtImpl as rpc.RemoteObject;
      };
    
      onDisconnect(want: Want): void {
        hilog.info(DOMAIN_NUMBER, TAG, `onDisconnect, want: ${want.abilityName}`);
      };
    
      onDestroy(): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onDestroy');
      };
    };
    
  4. 在工程Module對應的[module.json5配置文件]中注冊ServiceExtensionAbility,type標簽需要設置為“service”,srcEntry標簽表示當前ExtensionAbility組件所對應的代碼路徑。
    {
      "module": {
        ...
        "extensionAbilities": [
          {
            "name": "ServiceExtAbility",
            "icon": "$media:icon",
            "description": "service",
            "type": "service",
            "exported": true,
            "srcEntry": "./ets/ServiceExtAbility/ServiceExtAbility.ets"
          }
        ]
      }
    }
    

啟動一個后臺服務(僅對系統應用開放)

系統應用通過[startServiceExtensionAbility()]方法啟動一個后臺服務,服務的[onRequest()]回調就會被調用,并在該回調方法中接收到調用者傳遞過來的want對象。后臺服務啟動后,其生命周期獨立于客戶端,即使客戶端已經銷毀,該后臺服務仍可繼續運行。因此,后臺服務需要在其工作完成時通過調用ServiceExtensionContext的[terminateSelf()]來自行停止,或者由另一個組件調用[stopServiceExtensionAbility()]來將其停止。

說明: ServiceExtensionContext的[startServiceExtensionAbility()]、[stopServiceExtensionAbility()]和[terminateSelf()]為系統接口,三方應用不支持調用。

  1. 在系統應用中啟動一個新的ServiceExtensionAbility。示例中的context的獲取方式請參見[獲取UIAbility的上下文信息]。
    import common from '@ohos.app.ability.common';
    import Want from '@ohos.app.ability.Want';
    import { BusinessError } from '@ohos.base';
    import promptAction from '@ohos.promptAction';
    import hilog from '@ohos.hilog';
    
    const TAG: string = '[Page_ServiceExtensionAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Entry
    @Component
    struct Page_ServiceExtensionAbility {
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
                let want: Want = {
                  deviceId: '',
                  bundleName: 'com.samples.stagemodelabilitydevelop',
                  abilityName: 'ServiceExtAbility'
                };
                context.startServiceExtensionAbility(want).then(() = > {
                  hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ServiceExtensionAbility.');
                  // 成功啟動后臺服務
                  promptAction.showToast({
                    message: $r('app.string.SuccessfullyStartBackendService')
                  });
                }).catch((err: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`);
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    
  2. 在系統應用中停止一個已啟動的ServiceExtensionAbility。
    import common from '@ohos.app.ability.common';
    import hilog from '@ohos.hilog';
    import promptAction from '@ohos.promptAction';
    import Want from '@ohos.app.ability.Want';
    import { BusinessError } from '@ohos.base';
    
    const TAG: string = '[Page_ServiceExtensionAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Entry
    @Component
    struct Page_ServiceExtensionAbility {
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
                let want: Want = {
                  deviceId: '',
                  bundleName: 'com.samples.stagemodelabilitydevelop',
                  abilityName: 'ServiceExtAbility'
                };
                context.stopServiceExtensionAbility(want).then(() = > {
                  hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in stopping ServiceExtensionAbility.');
                  promptAction.showToast({
                    message: $r('app.string.SuccessfullyStoppedAStartedBackendService')
                  });
                }).catch((err: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to stop ServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`);
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    
  3. 已啟動的ServiceExtensionAbility停止自身。
    import common from '@ohos.app.ability.common';
    import { BusinessError } from '@ohos.base';
    import promptAction from '@ohos.promptAction';
    import hilog from '@ohos.hilog';
    import Want from '@ohos.app.ability.Want';
    
    const TAG: string = '[Page_ServiceExtensionAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Entry
    @Component
    struct Page_ServiceExtensionAbility {
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
                context.terminateSelf().then(() = > {
                  hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in terminating self.');
                  // 成功停止當前后臺服務
                  promptAction.showToast({
                    message: $r('app.string.SuccessfullyStopStartedBackendService')
                  });
                }).catch((err: BusinessError) = > {
                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    

說明: 后臺服務可以在后臺長期運行,為了避免資源浪費,需要對后臺服務的生命周期進行管理。即一個后臺服務完成了請求方的任務,需要及時銷毀。銷毀已啟動的后臺服務有兩種方式:

  • 后臺服務自身調用[terminateSelf()]方法來自行停止。
  • 由其他組件調用[stopServiceExtensionAbility()]方法來停止。 調用[terminateSelf()]或[stopServiceExtensionAbility()]方法之后,系統將銷毀后臺服務。

連接一個后臺服務

系統應用或者三方應用可以通過[connectServiceExtensionAbility()]連接一個服務(在Want對象中指定啟動的目標服務),服務的[onConnect()]就會被調用,并在該回調方法中接收到調用者傳遞過來的Want對象,從而建立長連接。

ServiceExtensionAbility服務組件在[onConnect()]中返回IRemoteObject對象,開發者通過該IRemoteObject定義通信接口,用于客戶端與服務端進行RPC交互。多個客戶端可以同時連接到同一個后臺服務,客戶端完成與服務的交互后,客戶端需要通過調用[disconnectServiceExtensionAbility()]來斷開連接。如果所有連接到某個后臺服務的客戶端均已斷開連接,則系統會銷毀該服務。

  • 使用connectServiceExtensionAbility()建立與后臺服務的連接。示例中的context的獲取方式請參見[獲取UIAbility的上下文信息]。
    import common from '@ohos.app.ability.common';
    import deviceManager from '@ohos.distributedDeviceManager';
    import hilog from '@ohos.hilog';
    import promptAction from '@ohos.promptAction';
    import rpc from '@ohos.rpc';
    import Want from '@ohos.app.ability.Want';
    // 客戶端需要將服務端對外提供的idl_service_ext_proxy.ts導入到本地工程中
    import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy';
    
    const TAG: string = '[Page_ServiceExtensionAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    let connectionId: number;
    let want: Want = {
      deviceId: '',
      bundleName: 'com.samples.stagemodelabilitydevelop',
      abilityName: 'ServiceExtAbility'
    };
    
    let options: common.ConnectOptions = {
      onConnect(elementName, remote: rpc.IRemoteObject): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');
        if (remote === null) {
          hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`);
          return;
        }
        let serviceExtProxy: IdlServiceExtProxy = new IdlServiceExtProxy(remote);
        // 通過接口調用的方式進行通信,屏蔽了RPC通信的細節,簡潔明了
        serviceExtProxy.processData(1, (errorCode: number, retVal: number) = > {
          hilog.info(DOMAIN_NUMBER, TAG, `processData, errorCode: ${errorCode}, retVal: ${retVal}`);
        });
        serviceExtProxy.insertDataToMap('theKey', 1, (errorCode: number) = > {
          hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, errorCode: ${errorCode}`);
        })
      },
      onDisconnect(elementName): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');
      },
      onFailed(code: number): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback', JSON.stringify(code));
      }
    };
    @Entry
    @Component
    struct Page_ServiceExtensionAbility {
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
                // 建立連接后返回的Id需要保存下來,在解綁服務時需要作為參數傳入
                connectionId = context.connectServiceExtensionAbility(want, options);
                // 成功連接后臺服務
                promptAction.showToast({
                  message: $r('app.string.SuccessfullyConnectBackendService')
                });
                // connectionId = context.connectAbility(want, options);
                hilog.info(DOMAIN_NUMBER, TAG, `connectionId is : ${connectionId}`);
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    
  • 使用disconnectServiceExtensionAbility()斷開與后臺服務的連接。
    import hilog from '@ohos.hilog';
    import promptAction from '@ohos.promptAction';
    import common from '@ohos.app.ability.common';
    import { BusinessError } from '@ohos.base';
    
    const TAG: string = '[Page_ServiceExtensionAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    let connectionId: number;
    @Entry
    @Component
    struct Page_ServiceExtensionAbility {
      build() {
        Column() {
          //...
          List({ initialIndex: 0 }) {
            ListItem() {
              Row() {
                //...
              }
              .onClick(() = > {
                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
                // connectionId為調用connectServiceExtensionAbility接口時的返回值,需開發者自行維護
                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');
                });
              })
            }
            //...
          }
          //...
        }
        //...
      }
    }
    

客戶端與服務端通信

客戶端在onConnect()中獲取到[rpc.RemoteObject]對象后便可與Service進行通信,有如下兩種方式:

  • 使用服務端提供的IDL接口進行通信(推薦
    // 客戶端需要將服務端對外提供的idl_service_ext_proxy.ts導入到本地工程中
    import common from '@ohos.app.ability.common';
    import hilog from '@ohos.hilog';
    import rpc from '@ohos.rpc';
    import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy';
    
    const TAG: string = '[Page_ServiceExtensionAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    let options: common.ConnectOptions = {
      onConnect(elementName, remote: rpc.IRemoteObject): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');
        if (remote === null) {
          hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`);
          return;
        }
        let serviceExtProxy: IdlServiceExtProxy = new IdlServiceExtProxy(remote);
        // 通過接口調用的方式進行通信,屏蔽了RPC通信的細節,簡潔明了
        serviceExtProxy.processData(1, (errorCode: number, retVal: number) = > {
          hilog.info(DOMAIN_NUMBER, TAG, `processData, errorCode: ${errorCode}, retVal: ${retVal}`);
        });
        serviceExtProxy.insertDataToMap('theKey', 1, (errorCode: number) = > {
          hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, errorCode: ${errorCode}`);
        })
      },
      onDisconnect(elementName): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');
      },
      onFailed(code: number): void {
        hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback', JSON.stringify(code));
      }
    };
    
  • 直接使用[sendMessageRequest]接口向服務端發送消息(不推薦)
    import hilog from '@ohos.hilog';
    import promptAction from '@ohos.promptAction';
    import rpc from '@ohos.rpc';
    import common from '@ohos.app.ability.common';
    import { BusinessError } from '@ohos.base';
    
    const TAG: string = '[Page_CollaborateAbility]';
    const DOMAIN_NUMBER: number = 0xFF00;
    const REQUEST_CODE = 1;
    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}`);
          // 成功連接后臺服務
          promptAction.showToast({
            message: `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');
      }
    };
    //...
    

服務端對客戶端身份校驗

部分開發者需要使用ServiceExtension提供一些較為敏感的服務,因此需要對客戶端身份進行校驗,開發者可在IDL接口的stub端進行校驗,IDL接口實現詳見上文[定義IDL接口],此處推薦兩種校驗方式:

  • 通過callerUid識別客戶端應用
    通過調用[getCallingUid()]接口獲取客戶端的uid,再調用[getBundleNameByUid()]接口獲取uid對應的bundleName,從而識別客戶端身份。此處需要注意的是[getBundleNameByUid()]是一個異步接口,因此服務端無法將校驗結果返回給客戶端,這種校驗方式適合客戶端向服務端發起執行異步任務請求的場景,示例代碼如下:
    import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
    import bundleManager from '@ohos.bundle.bundleManager';
    import IdlServiceExtStub from './idl_service_ext_stub';
    import hilog from '@ohos.hilog';
    import rpc from '@ohos.rpc';
    import type { BusinessError } from '@ohos.base';
    import type { InsertDataToMapCallback } from './i_idl_service_ext';
    import type { ProcessDataCallback } from './i_idl_service_ext';
    
    const ERR_OK = 0;
    const ERR_DENY = -1;
    const TAG: string = "[IdlServiceExtImpl]";
    const DOMAIN_NUMBER: number = 0xFF00;
    
    // 開發者需要在這個類型里對接口進行實現
    export default class ServiceExtImpl extends IdlServiceExtStub {
      processData(data: number, callback: ProcessDataCallback): void {
        // 開發者自行實現業務邏輯
        hilog.info(DOMAIN_NUMBER, TAG, `processData: ${data}`);
        let callerUid = rpc.IPCSkeleton.getCallingUid();
        bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) = > {
          hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName);
          // 對客戶端包名進行識別
          if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') { // 識別不通過
            hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject');
            return;
          }
          // 識別通過,執行正常業務邏輯
        }).catch((err: BusinessError) = > {
          hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message);
        });
        //...
      };
    
      insertDataToMap(key: string, val: number, callback: InsertDataToMapCallback): void {
        // 開發者自行實現業務邏輯
        hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, key: ${key}  val: ${val}`);
        callback(ERR_OK);
      };
    };
    
  • 通過callerTokenId對客戶端進行鑒權
    通過調用[getCallingTokenId()]接口獲取客戶端的tokenID,再調用[verifyAccessTokenSync()]接口判斷客戶端是否有某個具體權限,由于當前不支持自定義權限,因此只能校驗當前[系統所定義的權限]。示例代碼如下:
    import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
    import bundleManager from '@ohos.bundle.bundleManager';
    import IdlServiceExtStub from './idl_service_ext_stub';
    import hilog from '@ohos.hilog';
    import rpc from '@ohos.rpc';
    import type { BusinessError } from '@ohos.base';
    import type { InsertDataToMapCallback } from './i_idl_service_ext';
    import type { ProcessDataCallback } from './i_idl_service_ext';
    
    const ERR_OK = 0;
    const ERR_DENY = -1;
    const TAG: string = '[IdlServiceExtImpl]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    // 開發者需要在這個類型里對接口進行實現
    export default class ServiceExtImpl extends IdlServiceExtStub {
      processData(data: number, callback: ProcessDataCallback): void {
        // 開發者自行實現業務邏輯
        hilog.info(DOMAIN_NUMBER, TAG, `processData: ${data}`);
    
        let callerUid = rpc.IPCSkeleton.getCallingUid();
        bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) = > {
          hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName);
          // 對客戶端包名進行識別
          if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') { // 識別不通過
            hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject');
            return;
          }
          // 識別通過,執行正常業務邏輯
        }).catch((err: BusinessError) = > {
          hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message);
        });
    
        let callerTokenId = rpc.IPCSkeleton.getCallingTokenId();
        let accessManger = abilityAccessCtrl.createAtManager();
        // 所校驗的具體權限由開發者自行選擇,此處ohos.permission.GET_BUNDLE_INFO_PRIVILEGED只作為示例
        let grantStatus = accessManger.verifyAccessTokenSync(callerTokenId, 'ohos.permission.GET_BUNDLE_INFO_PRIVILEGED');
        if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
          hilog.info(DOMAIN_NUMBER, TAG, 'PERMISSION_DENIED');
          callback(ERR_DENY, data); // 鑒權失敗,返回錯誤
          return;
        }
        hilog.info(DOMAIN_NUMBER, TAG, 'verify access token success.');
        callback(ERR_OK, data + 1); // 鑒權通過,執行正常業務邏輯
      };
    
      insertDataToMap(key: string, val: number, callback: InsertDataToMapCallback): void {
        // 開發者自行實現業務邏輯
        hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, key: ${key}  val: ${val}`);
        callback(ERR_OK);
      };
    };
    

審核編輯 黃宇

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

    關注

    0

    文章

    403

    瀏覽量

    17527
  • 程序
    +關注

    關注

    117

    文章

    3795

    瀏覽量

    81303
  • 鴻蒙
    +關注

    關注

    57

    文章

    2392

    瀏覽量

    42980
收藏 人收藏

    評論

    相關推薦

    鴻蒙開發接口Ability框架:【@ohos.application.Ability (Ability)】

    Ability模塊提供對Ability生命周期、上下文環境等調用管理的能力,包括Ability創建、銷毀、轉儲客戶端信息等。
    的頭像 發表于 04-30 17:42 ?2320次閱讀
    <b class='flag-5'>鴻蒙</b>開發接口<b class='flag-5'>Ability</b><b class='flag-5'>框架</b>:【@ohos.application.<b class='flag-5'>Ability</b> (<b class='flag-5'>Ability</b>)】

    鴻蒙開發接口Ability框架:【@ohos.ability.featureAbility (FeatureAbility模塊)】

    FeatureAbility模塊提供帶有UI設計與用戶交互的能力,包括啟動新的ability、獲取dataAbilityHelper、設置此Page Ability、獲取當前Ability對應的窗口,連接
    的頭像 發表于 05-06 16:31 ?1042次閱讀
    <b class='flag-5'>鴻蒙</b>開發接口<b class='flag-5'>Ability</b><b class='flag-5'>框架</b>:【@ohos.<b class='flag-5'>ability</b>.featureAbility (FeatureAbility模塊)】

    鴻蒙開發接口Ability框架:【 (ServiceExtensionAbility)】

    ServiceExtensionAbility模塊提供ServiceExtension服務擴展相關接口的能力。
    的頭像 發表于 05-09 09:59 ?876次閱讀
    <b class='flag-5'>鴻蒙</b>開發接口<b class='flag-5'>Ability</b><b class='flag-5'>框架</b>:【 (<b class='flag-5'>ServiceExtensionAbility</b>)】

    鴻蒙開發接口Ability框架:【 (Context模塊)】

    Context模塊提供了ability或application的上下文的能力,包括允許訪問特定于應用程序的資源、請求和驗證權限等。
    的頭像 發表于 05-13 16:04 ?751次閱讀
    <b class='flag-5'>鴻蒙</b>開發接口<b class='flag-5'>Ability</b><b class='flag-5'>框架</b>:【 (Context模塊)】

    鴻蒙Ability Kit程序框架服務)【UIExtensionAbility】

    [UIExtensionAbility]是UI類型的ExtensionAbility組件,需要與[UIExtensionComponent]一起配合使用,開發者可以在UIAbility的頁面中通過UIExtensionComponent嵌入提供方應用的UIExtensionAbility提供的UI。UIExtensionAbility會在獨立于UIAbility的進程中運行,完成其頁面的布局和渲染。常用于有進程隔離訴求的系統彈窗、狀態欄、膠囊等模塊化開發的場景。
    的頭像 發表于 06-05 09:19 ?1465次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b>(<b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>)【UIExtensionAbility】

    HarmonyOS NEXT應用元服務開發Intents Kit(意圖框架服務)綜述

    一、綜述 Intents Kit(意圖框架服務)是HarmonyOS級的意圖標準體系 ,意圖連接了應用/元服務內的業務功能。 意圖框架能幫開
    發表于 11-28 10:43

    鴻蒙應用模型:【Ability Kit】簡介

    Ability Kit程序框架服務)提供了應用程序開發和運行的應用模型,是系統為開發者提供的應
    的頭像 發表于 05-29 14:41 ?693次閱讀
    <b class='flag-5'>鴻蒙</b>應用模型:【<b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b>】簡介

    鴻蒙Ability Kit程序框架服務)【Ability內頁面間的跳轉】

    基于Stage模型下的Ability開發,實現Ability內頁面間的跳轉和數據傳遞。
    的頭像 發表于 06-03 20:43 ?325次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b>(<b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>)【<b class='flag-5'>Ability</b>內頁面間的跳轉】

    鴻蒙Ability Kit程序框架服務)【ExtensionAbility組件】

    ExtensionAbility組件是基于特定場景(例如服務卡片、輸入法等)提供的應用組件,以便滿足更多的使用場景。
    的頭像 發表于 06-04 15:54 ?651次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b>(<b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>)【ExtensionAbility組件】

    鴻蒙Ability Kit程序框架服務)【AbilityServiceExtensionAbility通信】

    本示例展示通過[IDL的方式]和?[@ohos.rpc]?等接口實現了AbilityServiceExtensionAbility之間的通信。
    的頭像 發表于 06-05 09:28 ?526次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b>(<b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>)【<b class='flag-5'>Ability</b>與<b class='flag-5'>ServiceExtensionAbility</b>通信】

    鴻蒙Ability Kit程序框架服務)【組件啟動規則(Stage模型)】

    組件啟動規則(Stage模型) 啟動組件是指一切啟動或連接應用組件的行為: 啟動UIAbility、ServiceExtensionAbility、DataShareExtensionAbility
    的頭像 發表于 06-10 18:47 ?974次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b>(<b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>)【組件啟動規則(Stage模型)】

    鴻蒙Ability Kit程序框架服務)【應用啟動框架AppStartup】

    `AppStartup`提供了一種更加簡單高效的初始化組件的方式,支持異步初始化組件加速應用的啟動時間。使用啟動框架應用開發者只需要分別為待初始化的組件實現`AppStartup`提供
    的頭像 發表于 06-10 18:38 ?762次閱讀

    鴻蒙開發Ability Kit程序框架服務:任務管理

    AbilityRecord:系統服務側管理一個UIAbility實例的最小單元,對應一個應用側的UIAbility組件實例。系統服務側管理UIAbility實例數量上限為512個。
    的頭像 發表于 06-24 14:46 ?504次閱讀
    <b class='flag-5'>鴻蒙</b>開發<b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b><b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>:任務管理

    鴻蒙開發Ability Kit程序框架服務:FA模型綁定Stage模型ServiceExtensionAbility

    本文介紹FA模型的三種應用組件如何綁定Stage模型的ServiceExtensionAbility組件。
    的頭像 發表于 06-25 10:43 ?333次閱讀
    <b class='flag-5'>鴻蒙</b>開發<b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b><b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>:FA模型綁定Stage模型<b class='flag-5'>ServiceExtensionAbility</b>

    鴻蒙開發Ability Kit程序框架服務:ServiceAbility切換 組件切換

    FA模型中的ServiceAbility對應Stage模型中的ServiceExtensionAbility。Stage模型下的ServiceExtensionAbility為系統API,只有系統
    的頭像 發表于 06-28 10:24 ?365次閱讀
    <b class='flag-5'>鴻蒙</b>開發<b class='flag-5'>Ability</b> <b class='flag-5'>Kit</b><b class='flag-5'>程序</b><b class='flag-5'>框架</b><b class='flag-5'>服務</b>:ServiceAbility切換 組件切換
    主站蜘蛛池模板: 国产69TV精品久久久久99 | 蜜臀久久99精品久久久久久做爰 | 扒开 浓密 毛 | 大桥未久电影在线观看 | 免费看国产曰批40分钟 | 手机观看毛片 | 欧美人与动牲交XXXXBBBB免费 | 久久青草费线频观看国产 | 年轻的的小婊孑2中文字幕 你是淫荡的我的女王 | 竹菊精品久久久久久久99蜜桃 | 草莓西瓜樱桃香蕉直播视频 | 国产精品青草久久福利不卡 | 杨幂视频在线观看1分30秒 | 亚洲精品国产专区91在线 | 久久青草在线视频精品 | 国产午夜精品片一区二区三区 | 怡春院国产精品视频 | china年轻小帅脸直播飞机 | 高h 纯肉文 | 亚洲日本欧美日韩高观看 | 可以看的黄页的网站 | 在线欧美 精品 第1页 | 久久精品视频在线看99 | 在线精品国精品国产不卡 | 欧美阿v在线免播播放 | 一个人的免费完整在线观看HD | 久久伊人中文字幕有码 | 亚洲人成网站7777视频 | 欧美A级肉欲大片XXX | 日韩精品专区在线影院重磅 | 亚洲一卡二卡三卡四卡2021麻豆 | 国产乱人偷精品视频A人人澡 | 混乱家庭电影完整版在线看 | 精品国产乱码久久久久久人妻 | 女性露出奶头流出精子 | 亚洲一区免费看 | 性夜夜春夜夜爽AA片A | 国产在线视频分类精品 | 妖精视频免费看 | 亚洲AV日韩AV欧美在线观看网 | 国产成人在线视频网站 |