HarmonyOS 基礎(chǔ)技術(shù)賦能之公共事件(CommonEvent)開發(fā)
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
引言
在HarmonyOS通過CES(Common Event Service,公共事件服務(wù))為應(yīng)用程序提供訂閱、發(fā)布、退訂公共事件的能力。
公共事件可分為系統(tǒng)公共事件和自定義公共事件。
系統(tǒng)公共事件:系統(tǒng)將收集到的事件信息,根據(jù)系統(tǒng)策略發(fā)送給訂閱該事件的用戶程序。 公共事件包括:終端設(shè)備用戶可感知的亮滅屏事件,以及系統(tǒng)關(guān)鍵服務(wù)發(fā)布的系統(tǒng)事件(例如:USB插拔,網(wǎng)絡(luò)連接,系統(tǒng)升級)等。
自定義公共事件:應(yīng)用自定義一些公共事件用來處理業(yè)務(wù)邏輯。
場景介紹
每個應(yīng)用都可以訂閱自己感興趣的公共事件,訂閱成功后且公共事件發(fā)布后,系統(tǒng)會把其發(fā)送給應(yīng)用。這些公共事件可能來自系統(tǒng)、其他應(yīng)用和應(yīng)用自身。HarmonyOS提供了一套完整的API,支持用戶訂閱、發(fā)布和接收公共事件。發(fā)布公共事件需要借助CommonEventData對象,接收公共事件需要繼承CommonEventSubscriber類并實現(xiàn)onReceiveEvent回調(diào)函數(shù)。
開發(fā)者可以發(fā)布四種公共事件:無序的公共事件、帶權(quán)限的公共事件、有序的公共事件、粘性的公共事件。
本文主講無序的公共事件,其他類型事件,可參考華為官方開發(fā)文檔學(xué)習(xí)。
指南
1.發(fā)布公共事件:
- try {
- Intent intent = new Intent();
- Operation operation = new Intent.OperationBuilder()
- .withAction(“my.action”)//自定義字符串類型的action
- .build();
- intent.setOperation(operation);
- intent.setParam("result","commonEventData");
- intent.setParam("isCommonEvent",true);
- CommonEventData eventData = new CommonEventData(intent);
- CommonEventManager.publishCommonEvent(eventData);
- LogUtils.info(TAG,"PublishCommonEvent SUCCESS");
- } catch (RemoteException e) {
- LogUtils.error(TAG,"Exception occurred during publishCommonEvent invocation.");
- }
2. 訂閱公共事件
1)創(chuàng)建CommonEventSubscriber派生類,在onReceiveEvent()回調(diào)函數(shù)中處理公共事件。
- private class MyCommonEventSubscriber extends CommonEventSubscriber {
- MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
- super(info);
- }
- @Override
- public void onReceiveEvent(CommonEventData commonEventData) {
- }
2)構(gòu)造MyCommonEventSubscriber對象,調(diào)用CommonEventManager. subscribeCommonEvent()接口進(jìn)行訂閱。
- MatchingSkills matchingSkills = new MatchingSkills();
- //添加自定義的ation
- matchingSkills.addEvent(ACTION);
- matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_BOOT_COMPLETED); // 開機(jī)完成事件
- matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_CHARGING); // 正在充電事件
- CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
- subscriber = new MyCommonEventSubscriber(subscribeInfo);
- try {
- CommonEventManager.subscribeCommonEvent(subscriber);
- LogUtils.info(TAG,"SubscribeCommonEvent SUCCESS");
- } catch (RemoteException e) {
- LogUtils.error(TAG,"Exception occurred during subscribeCommonEvent invocation.");
- }
3)針對在onReceiveEvent中不能執(zhí)行耗時操作的限制,可以使用CommonEventSubscriber的goAsyncCommonEvent()來實現(xiàn)異步操作,函數(shù)返回后仍保持該公共事件活躍,且執(zhí)行完成后必須調(diào)用。
- // EventRunner創(chuàng)建新線程,將耗時的操作放到新的線程上執(zhí)行
- private EventRunner eventRunner=EventRunner.create();
- // MyEventHandler為EventHandler的派生類,在不同線程間分發(fā)和處理事件和Runnable任務(wù)
- private MyEventHandle myEventHandle=new MyEventHandle(eventRunner);
- private class MyCommonEventSubscriber extends CommonEventSubscriber {
- MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
- super(info);
- }
- @Override
- public void onReceiveEvent(CommonEventData commonEventData) {
- //以下為如果有耗時操作時,執(zhí)行的代碼
- final AsyncCommonEventResult result = goAsyncCommonEvent();
- Runnable runnable=new Runnable() {
- @Override
- public void run() {
- // 待執(zhí)行的操作,由開發(fā)者定義
- myEventHandle.sendEvent(100);
- result.finishCommonEvent(); // 調(diào)用finish結(jié)束異步操作
- }
- };
- myEventHandle.postTask(runnable);
- }
- }
- private class MyEventHandle extends EventHandler{
- public MyEventHandle(EventRunner runner) throws IllegalArgumentException {
- super(runner);
- }
- @Override
- protected void processEvent(InnerEvent event) {
- super.processEvent(event);
- //處理事件,由開發(fā)者撰寫
- int evnetID=event.eventId;
- LogUtils.info(TAG,"evnetID:"+evnetID);
- }
- }
3. 退訂公共事件:
- //在Ability的onStop()中調(diào)用CommonEventManager.unsubscribeCommonEvent()方法來退訂公共事件。調(diào)用后,之前訂閱的所有公共事件均被退訂。
- @Override
- protected void onStop() {
- super.onStop();
- try {
- CommonEventManager.unsubscribeCommonEvent(subscriber);
- LogUtils.info(TAG, "unsubscribeCommonEvent success.");
- } catch (RemoteException e) {
- LogUtils.error(TAG, "Exception occurred during unsubscribeCommonEvent invocation.");
- }
- }
實現(xiàn)效果
1.啟動APP時,如下圖:

2. 先點擊“訂閱公共事件”,后點擊“發(fā)布無序公共事件”。打印的log:
- 09-02 10:31:07.693 10390-10390/com.zel.commoneventdemo I 00000/LogUtil: MainAbilitySlice: SubscribeCommonEvent SUCCESS
- 09-02 10:31:09.795 10390-10390/com.zel.commoneventdemo I 00000/LogUtil: MainAbilitySlice: PublishCommonEvent SUCCESS
- 09-02 10:31:09.798 10390-10390/com.zel.commoneventdemo I 00000/LogUtil: MainAbilitySlice: action:action.send.message/result:commonEventData/isCommonEvent:true
- 09-02 10:31:09.799 10390-12455/com.zel.commoneventdemo I 00000/LogUtil: MainAbilitySlice: evnetID:100
附上源碼
1.MainAbilitySlice
- public class MainAbilitySlice extends AbilitySlice implements ClickedListener {
- private String TAG="MainAbilitySlice";
- private MyCommonEventSubscriber subscriber;
- private static final String ACTION="action.send.message";
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_main);
- Button btPublisher=(Button)findComponentById(ResourceTable.Id_btPublisher);
- Button btSubscriber=(Button)findComponentById(ResourceTable.Id_btSubscriber);
- btPublisher.setClickedListener(this);
- btSubscriber.setClickedListener(this);
- }
- @Override
- public void onActive() {
- super.onActive();
- }
- @Override
- public void onForeground(Intent intent) {
- super.onForeground(intent);
- }
- @Override
- public void onClick(Component component) {
- switch (component.getId()){
- case ResourceTable.Id_btPublisher:
- try {
- Intent intent = new Intent();
- Operation operation = new Intent.OperationBuilder()
- .withAction(ACTION)
- .build();
- intent.setOperation(operation);
- intent.setParam("result","commonEventData");
- intent.setParam("isCommonEvent",true);
- CommonEventData eventData = new CommonEventData(intent);
- CommonEventManager.publishCommonEvent(eventData);
- LogUtils.info(TAG,"PublishCommonEvent SUCCESS");
- } catch (RemoteException e) {
- LogUtils.error(TAG,"Exception occurred during publishCommonEvent invocation.");
- }
- break;
- case ResourceTable.Id_btSubscriber:
- MatchingSkills matchingSkills = new MatchingSkills();
- //添加自定義的ation
- matchingSkills.addEvent(ACTION);//自定義事件
- matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_BOOT_COMPLETED); // 開機(jī)完成事件
- matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_CHARGING); // 正在充電事件
- CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
- subscriber = new MyCommonEventSubscriber(subscribeInfo);
- try {
- CommonEventManager.subscribeCommonEvent(subscriber);
- LogUtils.info(TAG,"SubscribeCommonEvent SUCCESS");
- } catch (RemoteException e) {
- LogUtils.error(TAG,"Exception occurred during subscribeCommonEvent invocation.");
- }
- break;
- }
- }
- //// EventRunner創(chuàng)建新線程,將耗時的操作放到新的線程上執(zhí)行
- private EventRunner eventRunner=EventRunner.create();
- // MyEventHandler為EventHandler的派生類,在不同線程間分發(fā)和處理事件和Runnable任務(wù)
- private MyEventHandle myEventHandle=new MyEventHandle(eventRunner);
- private class MyCommonEventSubscriber extends CommonEventSubscriber {
- MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
- super(info);
- }
- /**
- * 針對在onReceiveEvent中不能執(zhí)行耗時操作的限制,可以使用CommonEventSubscriber的goAsyncCommonEvent()來實現(xiàn)異步操作,
- * 函數(shù)返回后仍保持該公共事件活躍,且執(zhí)行完成后必須調(diào)用AsyncCommonEventResult.finishCommonEvent()來結(jié)束。
- * @param commonEventData
- */
- @Override
- public void onReceiveEvent(CommonEventData commonEventData) {
- //非執(zhí)行耗時操作,以下代碼即可
- Intent intent=commonEventData.getIntent();
- String action= intent.getAction();
- switch (action){
- //自定義事件
- case ACTION:
- String result=intent.getStringParam("result");
- boolean isCommonEventData=intent.getBooleanParam("isCommonEvent",false);
- LogUtils.info(TAG,"action:"+action+"/result:"+result+"/isCommonEvent:"+isCommonEventData);
- break;
- // 開機(jī)完成事件
- case CommonEventSupport.COMMON_EVENT_BOOT_COMPLETED:
- LogUtils.info(TAG,"action:"+action);
- break;
- // 正在充電事件
- case CommonEventSupport.COMMON_EVENT_CHARGING:
- LogUtils.info(TAG,"action:"+action);
- break;
- }
- //以下為如果有耗時操作時,選擇執(zhí)行的代碼
- final AsyncCommonEventResult result = goAsyncCommonEvent();
- Runnable runnable=new Runnable() {
- @Override
- public void run() {
- // 待執(zhí)行的操作,由開發(fā)者定義
- myEventHandle.sendEvent(100);
- result.finishCommonEvent(); // 調(diào)用finish結(jié)束異步操作
- }
- };
- myEventHandle.postTask(runnable);
- }
- }
- private class MyEventHandle extends EventHandler{
- public MyEventHandle(EventRunner runner) throws IllegalArgumentException {
- super(runner);
- }
- @Override
- protected void processEvent(InnerEvent event) {
- super.processEvent(event);
- //處理事件,由開發(fā)者撰寫
- int evnetID=event.eventId;
- LogUtils.info(TAG,"evnetID:"+evnetID);
- }
- }
- @Override
- protected void onStop() {
- super.onStop();
- try {
- CommonEventManager.unsubscribeCommonEvent(subscriber);
- LogUtils.info(TAG, "unsubscribeCommonEvent success.");
- } catch (RemoteException e) {
- LogUtils.error(TAG, "Exception occurred during unsubscribeCommonEvent invocation.");
- }
- }
- }
2.LogUtils
- public class LogUtils {
- private static final String TAG_LOG = "LogUtil";
- private static final HiLogLabel LABEL_LOG = new HiLogLabel(0, 0, LogUtils.TAG_LOG);
- private static final String LOG_FORMAT = "%{public}s: %{public}s";
- private LogUtils() { }
- /**
- * Print debug log
- *
- * @param tag log tag
- * @param msg log message
- */
- public static void debug(String tag, String msg) {
- HiLog.debug(LABEL_LOG, LOG_FORMAT, tag, msg);
- }
- /**
- * Print info log
- *
- * @param tag log tag
- * @param msg log message
- */
- public static void info(String tag, String msg) {
- HiLog.info(LABEL_LOG, LOG_FORMAT, tag, msg);
- }
- /**
- * Print warn log
- *
- * @param tag log tag
- * @param msg log message
- */
- public static void warn(String tag, String msg) {
- HiLog.warn(LABEL_LOG, LOG_FORMAT, tag, msg);
- }
- /**
- * Print error log
- *
- * @param tag log tag
- * @param msg log message
- */
- public static void error(String tag, String msg) {
- HiLog.error(LABEL_LOG, LOG_FORMAT, tag, msg);
- }
- }
3. xml 布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:orientation="vertical"
- ohos:width="match_parent">
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:top_margin="50vp"
- ohos:orientation="vertical">
- <Button
- ohos:id="$+id:btPublisher"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="22vp"
- ohos:text_color="#ffffff"
- ohos:text="發(fā)布無序公共事件"
- ohos:padding="20vp"
- ohos:background_element="#00ffff"/>
- <Button
- ohos:id="$+id:btSubscriber"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="22vp"
- ohos:text_color="#ffffff"
- ohos:text="訂閱公共事件"
- ohos:padding="20vp"
- ohos:top_margin="30vp"
- ohos:background_element="#00ffff"/>
- </DirectionalLayout>
- </DirectionalLayout>
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)