往期鸿蒙5.0全套实战文章必看:(文中附带全栈鸿蒙5.0学习资料)
服务卡片显示问题定位指南
场景描述
众多应用在开发服务卡片时,会经常出现卡片白屏和卡片数据显示异常的问题。可能出现的原因是由于没有遵循卡片的约束限制,导致节点未正确挂载等一系列问题。
-
服务卡片使用出现白屏
现象:桌面上已加载的卡片,在开发调试过程中或者系统升级后突然出现白屏,遇到这种情况开发者常常不知如何排查这类问题。
分析:卡片白屏分为两种情况:白色绘制在FormComponent上,这个属于卡片没有正确加载;白色绘制在卡片内容的根节点上,这个属于卡片内容没有正常挂载,根据dump出ArkUI节点树、rsNode节点树进行判断。
1、抓取ArkUI节点树和rsNode节点树
- 保持手机亮屏状态,将以下代码生成"获取arkui控件节点树.bat"并双击,输入对应Focus window后回车即可得到ArkUI节点树
hdc shell param set persist.ace.debug.enabled 1 hdc shell "hidumper -s WindowManagerService -a '-a'" @set /p windowId=input WindowId : for /F %%i in ('hdc shell "find data/ -name arkui.dump"') do ( hdc shell "rm %%i" ) ::old pipeline ::hdc shell "hidumper -s WindowManagerService -a '-w %windowId% -render -c'" ::ng hdc shell "hidumper -s WindowManagerService -a '-w %windowId% -element -c'" > arkui.dump for /F %%i in ('hdc shell "find data/ -name arkui.dump"') do ( hdc file recv %%i . ) pause
- 抓取ArkUI节点树后,搜索应用名,通过compid判断是当前卡片的FormComponent,如下图,白色绘制在com.example.startability的FormComponent上,卡片默认颜色是透明色,如果出现白色,说明卡片被置成不可信卡片,这种情况大多是应用在代码里写了死循环导致阻塞JS线程等。
- 也可以通过DevEco Testing判断,如下图是修正代码后卡片正常展示的效果实用工具 --> UIViewer --> 获取页面 -->选中卡片 --> 此时展开右侧高亮Stack --> Common --> FormComponent即可查看。
- 根据以下代码生成"获取rs节点树.bat”文件,拿到rsNode节点树,通过上图ArkUI节点的CanvasNodeId找到对应的rsNode卡片根节点,根节点下面的节点就是卡片提供方的内容节点,从以下截图可以看出,白色绘制在卡片内容的根节点上,这种情况属于卡片正常加载了,但是卡片的内容没有加载,具体原因需要结合日志分析:
2、对照约束与限制检查代码是否符合规范。
注意点:
a. 对于共享包,不管是直接引入还是间接引入,都是不支持的。
b. 不支持断点调试&&不允许使用hilog(虽然部分开发者将hilog作为外部组件引入,导致IDE校验失败,但是实际上这是不合规范的,可能也会导致白卡的问题),推荐开发者使用原生console.log进行日志打印。
c. 对于是否支持的模块,注意区分卡片能力和元服务API,标识卡片能力的组件是支持在卡片内使用的。
d. 对于以memory://fileName) 的方式加载的图片,卡片的内存中只保留5张2M以下的图片,其他图片将会更新失败。
e. 对于定时刷新,系统规格最小间隔时间是30min,如需每分钟更新建议使用TextClock组件(不建议监听公共事件usual.event.TIME_TICK)。
3、取出全量日志,搜索关键字ArkCompiler,按照关键日志排查
a. 当出现关键字:Cannot get SourceMap info, dump raw stack一般是开发者的API写法错误,或者引入了不支持卡片的模块,导致了相关模块的报错,从而导致卡片内容加载失败出现白屏。
- 如果TypeError:Cannot read property xxx 的属性是业务自己的变量,业务方自己规避。如图,这是由于ZXGWidgetCardLarge.ts文件中使用startsWith的地方写法问题导致
- 如果TypeError:Cannot read property xxx 的属性是系统模块,需要明确当前模块是否支持服务卡片。若明确支持,需要进一步分析
b. 当出现关键字module can't load in form ,moduleName=xxx可能是预加载文件变更,与卡片服务白名单未匹配造成。需开发者去掉当前报错模块。
c. 当com.ohos.formrenderservice中出现关键日志can't find this page xxx一般是.abc文件打包时出现了问题,需要应用确认hap包里WidgetCard.abc是否存在,位置是否正确。建议Clean project后,重新编译运行
-
卡片数据更新异常
现象:卡片首次正常加载,点击卡片,主动更新图片数据时出现异常。
分析:卡片数据更新流程:Card.ets中触发postCardAction发送message事件,拉起FormExtensionAbility,然后由FormExtensionAbility调用updateForm将数据信息传输到卡片管理服务,经FMS将所有图片整合到imagemap中进行缓存,再由卡片渲染服务取出缓存信息进行组件渲染。这里卡片数据展示异常主要根据具体的实现逻辑结合日志一起分析。
以下是UpdateForm图片和数据传输流程:
1、关键日志FormManagerService,如果有Get file size failed, errno is 0这种Error信息说明开发者在updateForm时传的fd有问题,导致更新数据时,图片写入内存失败。
2、当出现关键日志formJsInfo.imageDataMap.size = xxx ,如果xxx与updateform传的图片数量一致,那么fms传给frs的图片信息正常,基本可以判断应用传递给imagemap写入图片数据正常。
3、当出现关键日志 load SharedMemoryImage timeout!一般是卡片内加载了多个网络图片,并超出了卡片内存限制。为防止图片占用内存太多,当前卡片的规格只保留5张2M以下的图片,其他图片30s后会被clear。
FAQ:
1、卡片数据存储在本地持久化数据里,依次添加多个卡片,手机重启后,卡片全部变成最新添加的。
A:手机重启,会重新走一遍AddForm回调,需要确认持久化数据是否为一对多
2、对于卡片内存的限制,除了控制在内存范围内,还有别的规避方案吗?
A:使用网络图片会有该限制,开发者可以将图片预置在resource中规避