1 关键字

SystemUI;notification;通知模板

2 问题描述

开发板型号:rk3568

内核版本:

问题现象:

  • systemui无法加载自定义通知模板

测试步骤:

  1. 在gitee上下载systemui-master分支代码,在本地进行编译、签名、打包;使用hdc将已签名的hap包安装到搭载OpenHarmony的设备上

  2. 安装发送带模板通知的Demo,发送模板通知

3 问题原因

3.1 正常机制

  • systemui接收到通知,下拉通知面板时展示模板通知

3.2 异常机制

  • systemui接收到通知,下拉通知面板无法展示通知

4 解决方案

通过自定义模块实现模板通知的展示

  • 1、在features/noticeitem/src/main/ets/com/ohos/noticeItem/view/item/目录下创建自定义模块:MyCustomItem.ets,内容如下:

import Constants, {NotificationItemData, NotificationLayout as Layout} from '../../common/constants';
​
const TAG = 'NoticeItem-CustomItem';
​
@Component
export default struct MyCustomItem {
  private customItemData: any = {};
​
  aboutToAppear() {
    console.log(TAG, `>>>> CustomItem aboutToAppear; customItemData = ${JSON.stringify(this.customItemData)}`);
  }
​
  build() {
    Column() {
      Row(){
        Image(this.customItemData.smallIcon)
          .objectFit(ImageFit.Contain)
          .width(Layout.TITLE_IMAGE_SIZE)
          .height(Layout.TITLE_IMAGE_SIZE)
​
        Text(this.customItemData.appName)
          .fontColor($r("sys.color.ohos_fa_text_primary"))
          .fontSize($r("sys.float.ohos_id_text_size_body3"))
          .fontWeight(FontWeight.Regular)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .maxLines(Constants.SINGLE_LINE)
      }
​
      Column(){
        Text(`template name: ${this.customItemData.template.name}`)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .fontSize($r("sys.float.ohos_id_text_size_body2"))
          .fontWeight(FontWeight.Medium)
          .lineHeight(Layout.TEXT_LINE_HEIGHT)
        Text(`template data: ${JSON.stringify(this.customItemData.template.data)}`)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .fontSize($r("sys.float.ohos_id_text_size_body2"))
          .fontWeight(FontWeight.Medium)
          .lineHeight(Layout.TEXT_LINE_HEIGHT)
        Text(this.customItemData.title)
          .maxLines(Constants.SINGLE_LINE)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .fontColor("#00ff00")
          .fontSize($r("sys.float.ohos_id_text_size_body2"))
          .fontWeight(FontWeight.Medium)
          .lineHeight(Layout.TEXT_LINE_HEIGHT)
        Text(this.customItemData.text)
          .maxLines(Constants.SINGLE_LINE)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .fontColor("#ff00ff")
          .fontSize($r("sys.float.ohos_id_text_size_body2"))
          .fontWeight(FontWeight.Regular)
          .lineHeight(Layout.TEXT_LINE_HEIGHT)
      }
    }
    .alignItems(HorizontalAlign.Start)
  }
}
  • 2、在features/noticeitem/src/main/ets/com/ohos/noticeItem/view/item/notificationItem.ets模块中修改如下代码

//import CustomItem from './customItem';
import MyCustomItem from './MyCustomItem';
... ...
if (this.itemData.template?.name) {
        //CustomItem({ customItemData: this.itemData, clickAction: () => this.showDevicesDialog(), isSubItem: this.isSubItem });
        MyCustomItem({ customItemData: this.itemData });
      } else {
        GeneralItem({ itemData: this.itemData, clickAction: () => this.showDevicesDialog(), isSubItem: this.isSubItem })
      }
  • 3、重新编译、打包、安装systemui

  • 4、发送带模板的通知,得到如下自定义通知展示

5 定位过程

  • 1、根据日志显示通知已发送成功

  • 通知模板的内容是

  • 2、根据systemui中通知的展示可知,带有模板的通知是由features/noticeitem/src/main/ets/com/ohos/noticeItem/view/item/customItem.ets组件进行渲染

Column() {
      if (this.itemData.template?.name) {
        //如果通知的template不为空则渲染CustomItem组件
        CustomItem({ customItemData: this.itemData, clickAction: () => this.showDevicesDialog(), isSubItem: this.isSubItem });
      } else {
        GeneralItem({ itemData: this.itemData, clickAction: () => this.showDevicesDialog(), isSubItem: this.isSubItem })
      }
    }

在CustomItem组件中通过日志可以得到验证

  • 3、通过CustomItem模块日志输出,可知ViewModel模块中获取到template为空

ViewModel.getPluginTempLate(this.customItemData.template.name);

 

  • 4、ViewModel模块中getPluginComponent方法调用的是NotificationService中的方法

getPluginTempLate(templateName) {
    Log.showInfo(TAG, 'getPluginTempLate: ' + templateName);
    return NotificationService.getPluginTempLate(templateName)
  }
  • 5、通过日志可知NotificationService中getPluginComponent方法最终返回为空,也就说明NotificationManager.NotificationTemplateMap为空,即:在NotificationManager中并未对NotificationTemplateMap进行赋值

getPluginTempLate(templateName) {
    Log.showInfo(TAG, `getPluginTempLate param:${templateName}`);
    let pluginTempLate = null;
    if (NotificationManager.NotificationTemplateMap !== null) {
      pluginTempLate = NotificationManager.NotificationTemplateMap.get(templateName);
    }
    Log.showInfo(TAG, `getPluginTempLate pluginTempLate:${JSON.stringify(pluginTempLate)}`);
    return pluginTempLate;
  }

  • 6、在NotificationManager中对NotificationTemplateMap进行赋值的方法如下,最终通过日志输出NotificationTemplateMap为空,表示NotificationManager对NotificationTemplateMap赋值失败

static requestTemplate(tag, ownerWant, templateName, templatePath) {
    Log.showInfo(TAG, `requestTemplate from: ${tag}`);
​
    let reqWant = {
      bundleName: '',
      abilityName: ''
    };
    let reqData = {}
​
    let requestParam = {
      owner: ownerWant,
      want: reqWant,
      name: templateName,
      data: reqData,
      jsonPath: templatePath
    };
​
    Log.showInfo(TAG, `requestTemplate requestParam: ${JSON.stringify(requestParam)}`)
    NotificationManager.request(tag, requestParam, (err, data) => {
      Log.showInfo(TAG, `request finished err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`)
      Log.showInfo(TAG, `request finished templateData: ${templateName} data: ${JSON.stringify(data.componentTemplate)}`)
      if (data?.componentTemplate?.source) {
        Log.showInfo(TAG, `request finished data.componentTemplate.source:${JSON.stringify(data.componentTemplate.source)}`)
        let templates = JSON.parse(data.componentTemplate.source);
        Log.showInfo(TAG, `request templates: ${JSON.stringify(templates)}`)
        for (let key in templates) {
          NotificationManager.NotificationTemplateMap.set(key, {
            "source": templates[key], "ability": ""
          });
        }
      }
    });
    Log.showInfo(TAG, `NotificationManager NotificationTemplateMap: ${JSON.stringify(NotificationManager.NotificationTemplateMap)}`)
  }

结论:由于NotificationTemplateMap赋值失败导致PluginComponent无法正常渲染,systemui无法加载带有模板的通知;因此可以自定义模块(不使用PluginComponent组件)来进行模板通知渲染

6 知识分享

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐