HarmonyOS 基础技术赋能之 公共事件(CommonEvent)开发 原创 精华

软通张二龙
发布于 2021-9-2 15:22
浏览
11收藏

HarmonyOS 基础技术赋能之 公共事件(CommonEvent)开发-鸿蒙开发者社区

引言

在HarmonyOS通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。

公共事件可分为系统公共事件自定义公共事件

系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。 公共事件包括:终端设备用户可感知的亮灭屏事件以及系统关键服务发布的系统事件(例如:USB插拔,网络连接,系统升级)等。

自定义公共事件:应用自定义一些公共事件用来处理业务逻辑。

场景介绍

每个应用都可以订阅自己感兴趣的公共事件,订阅成功后且公共事件发布后,系统会把其发送给应用。这些公共事件可能来自系统、其他应用和应用自身。HarmonyOS提供了一套完整的API,支持用户订阅、发布和接收公共事件。发布公共事件需要借助CommonEventData对象,接收公共事件需要继承CommonEventSubscriber类并实现onReceiveEvent回调函数。

开发者可以发布四种公共事件:无序的公共事件、带权限的公共事件、有序的公共事件、粘性的公共事件。

本文主讲无序的公共事件,其他类型事件,可参考华为官方开发文档学习。

指南

1.发布公共事件:

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)创建CommonEventSubscriber派生类,在onReceiveEvent()回调函数中处理公共事件。

private class MyCommonEventSubscriber extends CommonEventSubscriber {
    MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
     super(info);
 }

 @Override
 public void onReceiveEvent(CommonEventData commonEventData) {
}

2)构造MyCommonEventSubscriber对象,调用CommonEventManager. subscribeCommonEvent()接口进行订阅。

MatchingSkills matchingSkills = new MatchingSkills();
//添加自定义的ation
matchingSkills.addEvent(ACTION); 
matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_BOOT_COMPLETED); // 开机完成事件
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中不能执行耗时操作的限制,可以使用CommonEventSubscriber的goAsyncCommonEvent()来实现异步操作,函数返回后仍保持该公共事件活跃,且执行完成后必须调用。

// EventRunner创建新线程,将耗时的操作放到新的线程上执行
 private EventRunner eventRunner=EventRunner.create();

// MyEventHandler为EventHandler的派生类,在不同线程间分发和处理事件和Runnable任务
 private MyEventHandle myEventHandle=new MyEventHandle(eventRunner);

 private class MyCommonEventSubscriber extends CommonEventSubscriber {
     MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
      super(info);
  }
  @Override
  public void onReceiveEvent(CommonEventData commonEventData) {
        //以下为如果有耗时操作时,执行的代码
        final AsyncCommonEventResult result = goAsyncCommonEvent();
        Runnable runnable=new Runnable() {
         @Override
         public void run() {
           // 待执行的操作,由开发者定义
           myEventHandle.sendEvent(100);

           result.finishCommonEvent(); // 调用finish结束异步操作
         }
       };
       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);
     //处理事件,由开发者撰写
     int evnetID=event.eventId;
     LogUtils.info(TAG,"evnetID:"+evnetID);

   }
 }

3. 退订公共事件:

 //在Ability的onStop()中调用CommonEventManager.unsubscribeCommonEvent()方法来退订公共事件。调用后,之前订阅的所有公共事件均被退订。
   @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.");
  }
}

 实现效果

1.启动APP时,如下图:

HarmonyOS 基础技术赋能之 公共事件(CommonEvent)开发-鸿蒙开发者社区

2. 先点击“订阅公共事件”,后点击“发布无序公共事件”。打印的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); // 开机完成事件
        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创建新线程,将耗时的操作放到新的线程上执行
   private EventRunner eventRunner=EventRunner.create();

  // MyEventHandler为EventHandler的派生类,在不同线程间分发和处理事件和Runnable任务
   private MyEventHandle myEventHandle=new MyEventHandle(eventRunner);

   private class MyCommonEventSubscriber extends CommonEventSubscriber {
       MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
        super(info);
    }

     /**
      * 针对在onReceiveEvent中不能执行耗时操作的限制,可以使用CommonEventSubscriber的goAsyncCommonEvent()来实现异步操作,
      * 函数返回后仍保持该公共事件活跃,且执行完成后必须调用AsyncCommonEventResult.finishCommonEvent()来结束。
      * @param commonEventData
      */
    @Override
    public void onReceiveEvent(CommonEventData commonEventData) {
          //非执行耗时操作,以下代码即可
          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;
            // 开机完成事件
            case CommonEventSupport.COMMON_EVENT_BOOT_COMPLETED:
              LogUtils.info(TAG,"action:"+action);
              break;
            // 正在充电事件
            case CommonEventSupport.COMMON_EVENT_CHARGING:
              LogUtils.info(TAG,"action:"+action);
              break;
          }


          //以下为如果有耗时操作时,选择执行的代码
          final AsyncCommonEventResult result = goAsyncCommonEvent();
          Runnable runnable=new Runnable() {
           @Override
           public void run() {
             // 待执行的操作,由开发者定义
             myEventHandle.sendEvent(100);


             result.finishCommonEvent(); // 调用finish结束异步操作
           }
         };
         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);
       //处理事件,由开发者撰写
       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="发布无序公共事件"
      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>

更多原创内容请关注:软通动力HarmonyOS学院

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
12
收藏 11
回复
举报
2条回复
按时间正序
/
按时间倒序
软通动力HOS
软通动力HOS

张老师这段时间很高产

回复
2021-9-2 15:50:47
软通田可辉
软通田可辉

张老师很勤快

回复
2021-9-2 17:10:00
回复
    相关推荐