鴻蒙OS 公共事件開發(fā)指導(dǎo)

2020-09-18 11:06 更新

場(chǎng)景介紹

每個(gè)應(yīng)用都可以訂閱自己感興趣的公共事件,訂閱成功后且公共事件發(fā)布后,系統(tǒng)會(huì)把其發(fā)送給應(yīng)用。這些公共事件可能來自系統(tǒng)、其他應(yīng)用和應(yīng)用自身。HarmonyOS 提供了一套完整的 API,支持用戶訂閱、發(fā)送和接收公共事件。發(fā)送公共事件需要借助 CommonEventData 對(duì)象,接收公共事件需要繼承 CommonEventSubscriber 類并實(shí)現(xiàn) onReceiveEvent 回調(diào)函數(shù)。

接口說明

公共事件相關(guān)基礎(chǔ)類包含 CommonEventData、CommonEventPublishInfo、CommonEventSubscribeInfo、CommonEventSubscriber 和 CommonEventManager?;A(chǔ)類之間的關(guān)系如下圖所示:

圖1 公共事件基礎(chǔ)類關(guān)系圖 點(diǎn)擊放大

CommonEventData

CommonEventData 封裝公共事件相關(guān)信息。用于在發(fā)布、 分發(fā)和接收時(shí)處理數(shù)據(jù)。在構(gòu)造 CommonEventData 對(duì)象時(shí),相關(guān)參數(shù)需要注意以下事項(xiàng):

  • code 為有序公共事件的結(jié)果碼,data 為有序公共事件的結(jié)果數(shù)據(jù),僅用于有序公共事件場(chǎng)景。
  • intent 不允許為空,否則發(fā)布公共事件失敗。
接口名 描述
CommonEventData() 創(chuàng)建公共事件數(shù)據(jù)。
CommonEventData(Intent intent) 創(chuàng)建公共事件數(shù)據(jù)指定 Intent。
CommonEventData(Intent intent, int code, String data) 創(chuàng)建公共事件數(shù)據(jù),指定 Intent、code 和 data。
getIntent() 獲取公共事件intent。
setCode(int code) 設(shè)置有序公共事件的結(jié)果碼。
getCode() 獲取有序公共事件的結(jié)果碼。
setData(String data) 設(shè)置有序公共事件的詳細(xì)結(jié)果數(shù)據(jù)。
getData() 獲取有序公共事件的詳細(xì)結(jié)果數(shù)據(jù)。

CommonEventPublishInfo

CommonEventPublishInfo 封裝公共事件發(fā)布相關(guān)屬性、限制等信息,包括公共事件類型(有序或粘性)、接收者權(quán)限等。

有序公共事件:主要場(chǎng)景是多個(gè)訂閱者有依賴關(guān)系或者對(duì)處理順序有要求,例如:高優(yōu)先級(jí)訂閱者可修改公共事件內(nèi)容或處理結(jié)果,包括終止公共事件處理;或者低優(yōu)先級(jí)訂閱者依賴高優(yōu)先級(jí)的處理結(jié)果等。

有序公共事件的訂閱者可以通過 CommonEventSubscribeInfo.setPriority() 方法指定優(yōu)先級(jí),缺省為 0,優(yōu)先級(jí)范圍[-1000, 1000],值越大優(yōu)先級(jí)越高。

  • 粘性公共事件:指公共事件的訂閱動(dòng)作是在公共事件發(fā)布之后進(jìn)行,訂閱者也能收到的公共事件類型。主要場(chǎng)景是由公共事件服務(wù)記錄某些系統(tǒng)狀態(tài),如藍(lán)牙、WLAN、充電等事件和狀態(tài)。不使用粘性公共事件機(jī)制時(shí),應(yīng)用可以通過直接訪問系統(tǒng)服務(wù)獲取該狀態(tài);在狀態(tài)變化時(shí),系統(tǒng)服務(wù)、硬件需要提供類似 observer 等方式通知應(yīng)用。

發(fā)布粘性公共事件可以通過 setSticky() 方法設(shè)置, 發(fā)布粘性公共事件需要申請(qǐng)如下權(quán)限。聲明請(qǐng)參考[表1]。

    "reqPermissions": [{
        "name": "ohos.permission.COMMONEVENT_STICKY",
        "reason": "get right",
        "usedScene": {
           "ability": [
            ".MainAbility"
           ],
           "when": "inuse"
        }
    }, {
    ...
    }]
接口名 描述
CommonEventPublishInfo() 創(chuàng)建公共事件發(fā)送信息。
CommonEventPublishInfo(CommonEventPublishInfo publishInfo) 拷貝一個(gè)公共事件發(fā)送信息。
setSticky(boolean sticky) 設(shè)置公共事件的粘性屬性。
setOrdered(boolean ordered) 設(shè)置公共事件的有序?qū)傩浴?/td>
setSubscriberPermissions(String[] subscriberPermissions) 設(shè)置公共事件訂閱者的權(quán)限,多參數(shù)僅第一個(gè)生效。

CommonEventSubscribeInfo

CommonEventSubscribeInfo 封裝公共事件訂閱相關(guān)信息,比如優(yōu)先級(jí)、線程模式、事件范圍等。

線程模式(ThreadMode):設(shè)置訂閱者的回調(diào)方法執(zhí)行的線程模式。ThreadMode 有 HANDLER,POST,ASYNC,BACKGROUND 四種模式,目前只支持 HANDLER 模式。

  • HANDLER:在 Ability 的主線程上執(zhí)行。
  • POST:在事件分發(fā)線程執(zhí)行。
  • ASYNC:在一個(gè)新創(chuàng)建的異步線程執(zhí)行。
  • BACKGROUND:在后臺(tái)線程執(zhí)行。
接口名 描述
CommonEventSubscribeInfo(MatchingSkills matchingSkills) 創(chuàng)建公共事件訂閱器指定matchingSkills。
CommonEventSubscribeInfo(CommonEventSubscribeInfo) 拷貝公共事件訂閱器對(duì)象。
setPriority(int priority) 設(shè)置優(yōu)先級(jí),用于有序公共事件。
setThreadMode(ThreadMode threadMode) 指定訂閱者的回調(diào)函數(shù)運(yùn)行在哪個(gè)線程上。
setPermission(String permission) 設(shè)置訂閱者的權(quán)限。
setDeviceId(String deviceId) 指定訂閱哪臺(tái)設(shè)備的公共事件。

CommonEventSubscriber

CommonEventSubscriber 封裝公共事件訂閱者及相關(guān)參數(shù)。

  • CommonEventSubscriber.AsyncCommonEventResult 類處理有序公共事件異步執(zhí)行,詳見API參考。
  • 目前只能通過調(diào)用 [CommonEventManager] 的 subscribeCommonEvent() 進(jìn)行訂閱。
接口名 描述
CommonEventSubscriber(CommonEventSubscribeInfo subscribeInfo) 構(gòu)造公共事件訂閱者實(shí)例。
onReceiveEvent(CommonEventData data) 由開發(fā)者實(shí)現(xiàn), 在接收到公共事件時(shí)被調(diào)用。
AsyncCommonEventResult goAsyncCommonEvent() 設(shè)置有序公共事件異步執(zhí)行。
setCodeAndData(int code, String data) 設(shè)置有序公共事件的異步結(jié)果。
setData(String data) 設(shè)置有序公共事件的異步結(jié)果數(shù)據(jù)。
setCode(int code) 設(shè)置有序公共事件的異步結(jié)果碼。
getData() 獲取有序公共事件的異步結(jié)果數(shù)據(jù)。
getCode() 獲取有序公共事件的異步結(jié)果碼。
abortComonEvent() 取消當(dāng)前的公共事件,僅對(duì)有序公共事件有效,取消后,公共事件不再向下一個(gè)訂閱者傳遞。
getAbortCommonEvent() 獲取當(dāng)前有序公共事件是否取消的狀態(tài)。
clearAbortCommonEvent() 清除當(dāng)前有序公共事件abort狀態(tài)。
isOrderedCommonEvent() 查詢當(dāng)前公共事件的是否為有序公共事件。
isStickyCommonEvent() 查詢當(dāng)前公共事件是為否粘性公共事件。

CommonEventManager

CommonEventManager 是為應(yīng)用提供訂閱、退訂和發(fā)布公共事件的靜態(tài)接口類。

方法 描述
publishCommonEvent(CommonEventData event) 發(fā)布公共事件。
publishCommonEvent(CommonEventData event, CommonEventPublishInfo publishinfo) 發(fā)布公共事件指定發(fā)布信息。
publishCommonEvent(CommonEventData event, CommonEventPublishInfo publishinfo, CommonEventSubscriber resultSubscriber) 發(fā)布有序公共事件,指定發(fā)布信息和最后一個(gè)接收者。
subscribeCommonEvent(CommonEventSubscriber subscriber) 訂閱公共事件。
unsubscribeCommonEvent(CommonEventSubscriber subscriber) 退訂公共事件。

發(fā)布公共事件

開發(fā)者可以發(fā)布四種公共事件:無序的公共事件、帶權(quán)限的公共事件、有序的公共事件、粘性的公共事件。

發(fā)布無序的公共事件:構(gòu)造 CommonEventData 對(duì)象,設(shè)置 Intent,通過構(gòu)造operation 對(duì)象把需要發(fā)布的公共事件信息傳入 intent 對(duì)象。然后調(diào)用 CommonEventManager.publishCommonEvent(CommonEventData) 接口發(fā)布公共事件。

try {
     Intent intent = new Intent();   
     Operation operation = new Intent.OperationBuilder()
             .withAction("com.my.test")
             .build();
     intent.setOperation(operation);
     CommonEventData eventData = new CommonEventData(intent);
     CommonEventManager.publishCommonEvent(eventData); 
} catch (RemoteException e) {
     HiLog.info(LABEL, "publishCommonEvent occur exception."); 
}

發(fā)布攜帶權(quán)限的公共事件:構(gòu)造 CommonEventPublishInfo 對(duì)象,設(shè)置訂閱者的權(quán)限。

  {
      "reqPermissions": [{
          "name": "com.example.MyApplication.permission",
          "reason": "get right",
          "usedScene": {
             "ability": [
              ".MainAbility"
             ],
             "when": "inuse"
          }
      }, {
      ...
      }]
  }

  • 發(fā)布帶權(quán)限的公共事件示例代碼如下:

  Intent intent = new Intent();
  Operation operation = new Intent.OperationBuilder()
          .withAction("com.my.test")
          .build();
  intent.setOperation(operation);
  CommonEventData eventData = new CommonEventData(intent);
  CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
  String[] permissions = {"com.example.MyApplication.permission" };
  publishInfo.setSubscriberPermissions(permissions); // 設(shè)置權(quán)限
  try {   
       CommonEventManager.publishCommonEvent(eventData, publishInfo); 
  } catch (RemoteException e) {
       HiLog.info(LABEL, "publishCommoneEvent occur exception."); 
  }

發(fā)布有序的公共事件:構(gòu)造 CommonEventPublishInfo 對(duì)象,通過 setOrdered(true) 指定公共事件屬性為有序公共事件,也可以指定一個(gè)最后的公共事件接收者。

CommonEventSubscriber resultSubscriber = new MyCommonEventSubscriber();
CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
publishInfo.setOrdered(true); // 設(shè)置屬性為有序公共事件
try {   
    CommonEventManager.publishCommonEvent(eventData, publishInfo, resultSubscriber); // 指定resultSubscriber為有序公共事件最后一個(gè)接收者。
} catch (RemoteException e) {
    HiLog.info(LABEL, "publishCommoneEvent occur exception."); 
}

發(fā)布粘性公共事件:構(gòu)造 CommonEventPublishInfo 對(duì)象,通過 setSticky(true) 指定公共事件屬性為粘性公共事件。

  1. 發(fā)布者首先在 config.json 中申請(qǐng)發(fā)布粘性公共事件所需的權(quán)限,各字段含義詳見權(quán)限申請(qǐng)字段說明。

   {
       "reqPermissions": [{
           "name": "ohos.permission.COMMONEVENT_STICKY",
           "reason": "get right",
           "usedScene": {
              "ability": [
               ".MainAbility"
              ],
              "when": "inuse"
           }
       }, {
       ...
       }]
   }

  1. 發(fā)布粘性公共事件。

   CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
   publishInfo.setSticky(true); // 設(shè)置屬性為粘性公共事件
   try {   
       CommonEventManager.publishCommonEvent(eventData, publishInfo); 
   } catch (RemoteException e) {
       HiLog.info(LABEL, "publishCommoneEvent occur exception."); 
   }

訂閱公共事件

  1. 創(chuàng)建 CommonEventSubscriber 派生類,在 onReceiveEvent() 回調(diào)函數(shù)中處理公共事件。

說明

此處不能執(zhí)行耗時(shí)操作,否則會(huì)阻塞 UI 線程,產(chǎn)生用戶點(diǎn)擊沒有反應(yīng)等異常。

   class MyCommonEventSubscriber extends CommonEventSubscriber { 
       MyCommonEventSubscriber(CommonEventSubscribeInfo info) { 
           super(info);   
       }
       @Override 
       public void onReceiveEvent(CommonEventData commonEventData) {
       } 
   }

  1. 構(gòu)造 MyCommonEventSubscriber 對(duì)象,調(diào)用 CommonEventManager.subscribeCommonEvent() 接口進(jìn)行訂閱。

   String event = "com.my.test";
   MatchingSkills matchingSkills = new MatchingSkills();
   filter.addEvent(event); // 自定義事件
   filter.addEvent(CommonEventSupport.COMMON_EVENT_SCREEN_ON); // 亮屏事件
   CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
   MyCommonEventSubscriber subscriber = new MyCommonEventSubscriber(subscribeInfo);
   try {
       CommonEventManager.subscribeCommonEvent(subscriber); 
   } catch (RemoteException e) {
       HiLog.info(LABEL, "subscribeCommonEvent occur exception."); 
   }

如果訂閱擁有指定權(quán)限應(yīng)用發(fā)布的公共事件,發(fā)布者需要在 config.json 中申請(qǐng)權(quán)限,各字段含義詳見 權(quán)限申請(qǐng)字段說明。

   "reqPermissions": [
       {
           "name": "ohos.abilitydemo.permission.PROVIDER",
           "reason": "get right",
           "usedScene": {
               "ability": ["com.huawei.hmi.ivi.systemsetting.MainAbility"],
               "when": "inuse"
           }
       }
   ]

如果訂閱的公共事件是有序的,可以調(diào)用 setPriority()指定優(yōu)先級(jí)。

   String event = "com.my.test";
   MatchingSkills matchingSkills = new MatchingSkills();
   matchingSkills.addEvent(event ); // 自定義事件

    
   CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
   subscribeInfo.setPriority(100); // 設(shè)置優(yōu)先級(jí),優(yōu)先級(jí)取值范圍[-1000,1000],值默認(rèn)為0。
   MyCommonEventSubscriber subscriber = new MyCommonEventSubscriber(subscribeInfo);
   try {
        CommonEventManager.subscribeCommonEvent(subscriber); 
   } catch (RemoteException e) {
        HiLog.info(LABEL, "subscribeCommonEvent occur exception."); 
   }

  1. 針對(duì)在 onReceiveEvent 中不能執(zhí)行耗時(shí)操作的限制,可以使用 CommonEventSubscriber 的 goAsyncCommonEvent() 來實(shí)現(xiàn)異步操作,函數(shù)返回后仍保持該公共事件活躍,且執(zhí)行完成后必須調(diào)用 AsyncCommonEventResult .finishCommonEvent() 來結(jié)束。

   EventRunner runner = EventRunner.create(); //EventRunner 創(chuàng)建新線程,將耗時(shí)的操作放到新的線程上執(zhí)行
   MyEventHandler myHandler = new MyEventHandler(runner); //MyEventHandler 為 EventHandler 的派生類,在不同線程間分發(fā)和處理事件和 Runnable 任務(wù)
   @Override
   public void onReceiveEvent(CommonEventData commonEventData){
       final AsyncCommonEventResult result = goAsyncCommonEvent();

    
       Runnable task = new Runnable() {
           @Override
           public void run() {
               ........         // 待執(zhí)行的操作,由開發(fā)者定義
               result.finishCommonEvent(); // 調(diào)用finish結(jié)束異步操作
           }
       };
       myHandler.postTask(task);
   } 

退訂公共事件

在 Ability的onStop() 中調(diào)用 CommonEventManager.unsubscribeCommonEvent() 方法來退訂公共事件。調(diào)用后,之前訂閱的所有公共事件均被退訂。

try { 
    CommonEventManager.unsubscribeCommonEvent(subscriber);
 } catch (RemoteException e) {
    HiLog.info(LABEL, "unsubscribeCommonEvent occur exception.");
 }
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)