4

HarmonyOS学习路之开发篇——公共事件与通知(一)

 3 years ago
source link: https://my.oschina.net/gq105501/blog/5113170
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

公共事件与通知开发概述

HarmonyOS通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力,通过ANS(Advanced Notification Service,即通知增强服务)系统服务来为应用程序提供发布通知的能力。

  • 公共事件可分为系统公共事件和自定义公共事件。
    • 系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。例如:用户可感知亮灭屏事件,系统关键服务发布的系统事件(例如:USB插拔,网络连接,系统升级等)。
    • 自定义公共事件:应用自定义一些公共事件用来处理业务逻辑。
  • 通知提供应用的即时消息或通信消息,用户可以直接删除或点击通知触发进一步的操作。
  • IntentAgent封装了一个指定行为的Intent,可以通过IntentAgent启动Ability和发布公共事件。

应用如果需要接收公共事件,需要订阅相应的事件。

公共事件开发

公共事件相关基础类包含CommonEventData、CommonEventPublishInfo、CommonEventSubscribeInfo、CommonEventSubscriber和CommonEventManager。基础类之间的关系如下图所示:

图1 公共事件基础类关系图 在这里插入图片描述CommonEventData CommonEventData封装公共事件相关信息。用于在发布、分发和接收时处理数据。在构造CommonEventData对象时,相关参数需要注意以下事项:

  • code为有序公共事件的结果码,data为有序公共事件的结果数据,仅用于有序公共事件场景。
  • intent不允许为空,否则发布公共事件失败。

CommonEventPublishInfo CommonEventPublishInfo封装公共事件发布相关属性、限制等信息,包括公共事件类型(有序或粘性)、接收者权限等。

  • 有序公共事件:主要场景是多个订阅者有依赖关系或者对处理顺序有要求,例如:高优先级订阅者可修改公共事件内容或处理结果,包括终止公共事件处理;或者低优先级订阅者依赖高优先级的处理结果等。
  • 粘性公共事件:指公共事件的订阅动作是在公共事件发布之后进行,订阅者也能收到的公共事件类型。主要场景是由公共事件服务记录某些系统状态,如蓝牙、WLAN、充电等事件和状态。 CommonEventSubscribeInfo CommonEventSubscribeInfo封装公共事件订阅相关信息,比如优先级、线程模式、事件范围等。 线程模式(ThreadMode):设置订阅者的回调方法执行的线程模式。ThreadMode有HANDLER,POST,ASYNC,
    • BACKGROUND四种模式,目前只支持HANDLER模式。
    • HANDLER:在Ability的主线程上执行。
    • POST:在事件分发线程执行。
    • ASYNC:在一个新创建的异步线程执行。
    • BACKGROUND:在后台线程执行。

CommonEventSubscriber CommonEventSubscriber封装公共事件订阅者及相关参数。

  • CommonEventSubscriber.AsyncCommonEventResult类处理有序公共事件异步执行。
  • 目前只能通过调用CommonEventManagersubscribeCommonEvent()进行订阅。

CommonEventManager CommonEventManager是为应用提供订阅、退订和发布公共事件的静态接口类。

Demo实例程序

效果演示 HarmonyOS 公共事件Demo演示

发布公共事件

四种公共事件:无序的公共事件、带权限的公共事件、有序的公共事件、粘性的公共事件。 发布无序的公共事件:构造CommonEventData对象,设置Intent,通过构造operation对象把需要发布的公共事件信息传入intent对象。然后调用 CommonEventManager.publishCommonEvent(CommonEventData) 接口发布公共事件。

    public void publishDisorderedEvent() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withAction(event).build();
        intent.setOperation(operation);
        CommonEventData eventData = new CommonEventData(intent);
        try {
            CommonEventManager.publishCommonEvent(eventData);
            showTips(context, "Publish succeeded");
        } catch (RemoteException e) {
            HiLog.error(LABEL_LOG, "%{public}s", "publishDisorderedEvent remoteException.");
        }
    }

发布携带权限的公共事件:构造CommonEventPublishInfo对象,设置订阅者的权限。

  • 在config.json中申请所需的权限
    "reqPermissions": [
      {
        "name": "ohos.samples.permission",
        "reason": "get right",
        "usedScene": {
          "ability": [
            ".MainAbilitySlice"
          ],
          "when": "inuse"
        }
      }
    ]
  • 发布带权限的公共事件示例代码如下
public void publishPermissionEvent() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withAction(event).build();
        intent.setOperation(operation);
        CommonEventData eventData = new CommonEventData(intent);
        CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
        String[] permissions = {"ohos.sample.permission"};
        publishInfo.setSubscriberPermissions(permissions);
        try {
            CommonEventManager.publishCommonEvent(eventData, publishInfo);
            showTips(context, "Publish succeeded");
        } catch (RemoteException e) {
            HiLog.error(LABEL_LOG, "%{public}s", "publishPermissionEvent remoteException.");
        }
    }

发布有序的公共事件:构造CommonEventPublishInfo对象,通过setOrdered(true)指定公共事件属性为有序公共事件,也可以指定一个最后的公共事件接收者。

public void publishOrderlyEvent() {
        MatchingSkills skills = new MatchingSkills();
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withAction(event).build();
        intent.setOperation(operation);
        CommonEventData eventData = new CommonEventData(intent);
        skills.addEvent(event);
        CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
        publishInfo.setOrdered(true);
        try {
            CommonEventManager.publishCommonEvent(eventData, publishInfo);
            showTips(context, "Publish succeeded");
        } catch (RemoteException e) {
            HiLog.error(LABEL_LOG, "%{public}s", "publishOrderlyEvent remoteException.");
        }
    }

发布粘性公共事件:构造CommonEventPublishInfo对象,通过setSticky(true)指定公共事件属性为粘性公共事件。

  • 发布者首先在config.json中申请发布粘性公共事件所需的权限
    "reqPermissions": [
      {
        "name": "ohos.permission.COMMONEVENT_STICKY",
        "reason": "get right",
        "usedScene": {
          "ability": [
            ".MainAbilitySlice"
          ],
          "when": "inuse"
        }
      }
    ]
  • 发布粘性公共事件
public void publishStickyEvent() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withAction(event).build();
        intent.setOperation(operation);
        CommonEventData eventData = new CommonEventData(intent);
        CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
        publishInfo.setSticky(true);
        try {
            CommonEventManager.publishCommonEvent(eventData, publishInfo);
            showTips(context, "Publish succeeded");
        } catch (RemoteException e) {
            HiLog.error(LABEL_LOG, "%{public}s", "publishStickyEvent remoteException.");
        }
    }

订阅公共事件

1、创建CommonEventSubscriber派生类,在onReceiveEvent()回调函数中处理公共事件。

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

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

String event = "测试";
MatchingSkills matchingSkills = new MatchingSkills();
matchingSkills.addEvent(event); // 自定义事件
CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
TestCommonEventSubscribersubscriber = new TestCommonEventSubscriber(subscribeInfo);
try {
    CommonEventManager.subscribeCommonEvent(subscriber); 
} catch (RemoteException e) {
    HiLog.error(LABEL, "Exception occurred during subscribeCommonEvent invocation."); 
}

如果订阅的公共事件是有序的,可以调用setPriority()指定优先级。

String event = "测试";
MatchingSkills matchingSkills = new MatchingSkills();
matchingSkills.addEvent(event); // 自定义事件

CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
subscribeInfo.setPriority(100); // 设置优先级,优先级取值范围[-1000,1000],值默认为0。
TestCommonEventSubscribersubscriber subscriber = new TestCommonEventSubscribersubscriber (subscribeInfo);
try {
     CommonEventManager.subscribeCommonEvent(subscriber); 
} catch (RemoteException e) {
     HiLog.error(LABEL, "Exception occurred during subscribeCommonEvent invocation."); 
}

3、针对在onReceiveEvent中不能执行耗时操作的限制,可以使用CommonEventSubscriber的goAsyncCommonEvent()来实现异步操作,函数返回后仍保持该公共事件活跃,且执行完成后必须调用AsyncCommonEventResult .finishCommonEvent()来结束。

EventRunner runner = EventRunner.create(); // EventRunner创建新线程,将耗时的操作放到新的线程上执行
MyEventHandler myHandler = new MyEventHandler(runner); // MyEventHandler为EventHandler的派生类,在不同线程间分发和处理事件和Runnable任务
@Override
public void onReceiveEvent(CommonEventData commonEventData){
    final AsyncCommonEventResult result = goAsyncCommonEvent();

    Runnable task = new Runnable() {
        @Override
        public void run() {
            ........         // 待执行的操作,由开发者定义
            result.finishCommonEvent(); // 调用finish结束异步操作
        }
    };
    myHandler.postTask(task);
} 

退订公共事件

在Ability的onStop()中调用CommonEventManager.unsubscribeCommonEvent()方法来退订公共事件。调用后,之前订阅的所有公共事件均被退订。

public void unSubscribeEvent() {
        if (subscriber == null) {
            HiLog.info(LABEL_LOG, "%{public}s", "CommonEvent onUnsubscribe commonEventSubscriber is null");
            return;
        }
        try {
            CommonEventManager.unsubscribeCommonEvent(subscriber);
            showTips(context, "UnSubscribe succeeded");
        } catch (RemoteException e) {
            HiLog.error(LABEL_LOG, "%{public}s", "unsubscribeEvent remoteException.");
        }
        destroy();
    }

    private void destroy() {
        subscriber = null;
        eventListener = null;
        unSubscribe = true;
    }

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK