完整服务卡片项目开发【为Bilibili添加服务卡片】 原创 精华
2021.07.31@亮子力
BilibiliCards
项目预览视频播放地址:https://harmonyos.51cto.com/show/7536
项目开源gitee地址:https://gitee.com/liangzili/bilibili-cards
目录
介绍
这是一款纯鸿蒙版的哔哩哔哩服务卡片应用。
6月2日鸿蒙发布,今年的六月已经被鸿蒙刷屏了。从安卓到鸿蒙,最直观的变化应该就是服务卡片了。我也是在学习鸿蒙的同时,实际体验一下服务卡片的开发。
给大家看看最终的效果。
![]() |
![]() |
![]() |
---|---|---|
接下来分享下我的制作过程,我使用的开发环境是
IDE:DevEco Studio 2.1 Release
SDK:API Version 5
软件安装和项目建立的部分就跳过了,相信大家都比较熟悉了。直奔主题服务卡片的制作。
一、服务卡片设计
首先要先了解服务卡片,都有哪些尺寸,支持哪些组件,使用什么语言。然后规划好要实现哪些功能。
1.尺寸规格
服务卡片有4种尺寸,分别是微卡片、小卡片、中卡片、大卡片。官方提供了4种基础模板,12种高级模板。可以选择。基础模板如下图
2.功能设计
服务卡片设计的初衷就是信息显示、服务直达。依照这个原则,我找了几个Bilibili中我比较常用的功能,来制作服务卡片,比如追番列表。
3.开发语言
看下表就一目了然了,就是推荐JS。表格来源:
场景 | Java卡片 | JS卡片 | 支持的版本 |
---|---|---|---|
实时刷新(类似时钟) | Java使用ComponentProvider做实时刷新代价比较大 | JS可以做到端侧刷新,但是需要定制化组件 | HarmonyOS 2.0及以上 |
开发方式 | Java UI在卡片提供方需要同时对数据和组件进行处理,生成ComponentProvider远端渲染 | JS卡片在使用方加载渲染,提供方只要处理数据、组件和逻辑分离 | HarmonyOS 2.0及以上 |
组件支持 | Text、Image、DirectionalLayout、PositionLayout、DependentLayout | div、list、list-item、swiper、stack、image、text、span、progress、button(定制:chart 、clock、calendar) | HarmonyOS 2.0及以上 |
卡片内动效 | 不支持 | 暂不开放 | HarmonyOS 2.0及以上 |
阴影模糊 | 不支持 | 支持 | HarmonyOS 2.0及以上 |
动态适应布局 | 不支持 | 支持 | HarmonyOS 2.0及以上 |
自定义卡片跳转页面 | 不支持 | 支持 | HarmonyOS 2.0及以上 |
二、界面实现
本着学习的目的,卡片界面就不使用模板了。不过我们还是要通过IDE>>File>>New>>Service Widget来添加服务卡片,这样添加IDE会自动添加配置和管理相关文件。然后服务卡片的界面重新编写。服务卡片常用的的容器组件有div、list、stack、swiper等。我使用了4种尺寸的卡片,并尽可能的使用到所有的容器组件。
div:基础容器组件
就是用来划分区域的。比较常用。比如追番服务卡片。效果如图,代码如下
Note:其实这个服务卡片的布局,每一列的内容都是相同的,是应该使用list组件的。
list:列表容器组件
就如上面所说的连续相同的部分,可以使用这个组件,List不但可以显示更多的内容,而且代码更少。效果图如下
stack:堆叠容器组件
简单来说就是可以在一张图片上堆叠显示另一张图片,例如下图蓝框的图片覆盖在红框图片的上面。
swiper:滑动容器组件
正常情况下swiper是可以实现上下、左右滑动操作的。但是放置在桌面上的服务卡片,在左右滑动操作的时候,会使系统分不清楚用户是要左右滑动屏幕,还是左右滑动卡片。所以目前服务卡片的swiper容器是不支持手势滑动切换子组件的。下图是通过点击图片侧面的控制条实现上下滑动的。但是我个人觉得上下滑动其实还是挺好用的,毕竟在list组件上是可以上下滑动的,只可惜目前还不支持。
总结:服务卡片的设计比较简单,零基础也没关系,官方还贴心的准备了模板。只要挑选模板,设置变量也能快速构建。
三、API数据请求
卡片设计好之后,就需要通过Bilibili的API来获取数据了。主要就是给权限添加依赖,然后发送网络请求,通过API获取JSON的返回值,然后解析JSON得到我们需要的数据。
1.添加联网权限
要在config.json配置文件的module中添加:“reqPermissions”: [{“name”:“ohos.permission.INTERNET”}],
2.添加依赖包
找到entry/build.gradle文件,在dependencies下添加
3.http请求
以获取粉丝数为例。如果在浏览器中输入 https://api.bilibili.com/x/relation/stat?vmid=383565952 (其中vmid:是要查询的用户ID)
follower的值就是粉丝数。
网络访问我们可以使用HttpURLConnection,或者okhttp等依赖包,但是需要开启子线程、处理异常等操作,所以这里使用的是ZZR老师封装好的ZZRHttp
代码实现:
4.解析JSON
得到的是JSON格式的返回值,要得到follower的值,还需要对JSON进行数据解析。
先按照JSON的内容,生成JAVA类。代码如下。可以自己写,也可以百度搜 ”JSON生成Java实体类“,可直接生成。
总结:一定要添加联网权限不然是获取不到数据的。添加了2个依赖包,可以很方便的提取数据。获取其他的卡片数据的方式同理,不过代码比较多,就不一一展示了,感兴趣可以下载全量代码看。
四、数据更新
要想将数据更新到服务卡片,得先了解服务卡片的运作机制。如果是通过IDE>>File>>New>>Service Widget添加的服务卡片,那么在MainAbility中会添加卡片的生命周期回调方法,参考下面的代码。
1.定时更新
按照上述分析,我们只需要在config.json中开启服务卡片的周期性更新,在onUpdateForm(long formId)方法下执行数据获取更新。
config.json文件“abilities”的forms模块配置细节如下
这样结合我们在上一步获取API数据,解析JSON,开启服务卡片的周期性更新,就可以在updateFormData()实现服务卡片的数据更新了。截取follower数据更新的部分代码如下
2.手动更新
正常来说这样就可以正常更新数据了,但是会有个问题。就是在服务卡片首次创建添加到桌面的时候,在添加完的至少30分钟里,数据是不会更新的。此时如果在index.json中设置初始信息,那么在添加完成的前30分钟数据都是写死在data中的。如果不设置初始信息那么卡片就是空白的。
所以按照前面服务卡片的运作机制的分析,我们还需要在卡片初始化onCreateForm()的时候进行一次更新。这个非常简单用onCreateForm()调用onUpdateForm(formId)即可。
总结:这里的onUpdateForm(formId)中API的网络请求一定要新开一个子线程,不然会影响页面加载。这也是前面说的用ZZRhttp的原因。不过现在也遇到一个问题,当卡片数量变多时,同时在线更新这么多的卡片会变得非常缓慢,这个问题还有待解决。
五、功能直达
目前服务卡片仅支持click通用事件,事件类型:跳转事件(router)和消息事件(message)。详细说明参考官方文档
1.跳转事件
接下来实现与服务卡片的交互,当点击服务卡片时,会跳转到相应的页面,所以这里使用跳转事件。以番剧更新的卡片为例
1.首先我们要先添加一个要跳转的页面。如下图所示添加一个Page Ability,比如:VideoSlice
2.新建完成之后会增加VideoSlice和 slice/VideoSliceSlice 两个文件,和base/layout/ability_bilibili_page.xml页面文件
3.增加webview,将页面默认的Text控件修改为webview
4.在index.hml中给要触发的控件上添加onclick,比如:onclick=“routerEvent1”
5.在index.json中,添加对应的actions,跳转事件要多加一个参数"abilityName",指定要跳转的页面,并且携带参数url。
2.消息事件
这里使用视频动态服务卡片,做一个消息事件的测试,效果如下图,点击左右边,实现服务卡片的滑动。在小卡片上这样的操作体验不好。所以消息事件中的例子,只是为了测试,并没有加到项目里。
1.在index.hml中给要触发的控件上添加onclick,比如:onclick=“sendMessageEvent”
2.在index.json中,添加对应的actions
3.如果是消息事件(message)当点击带有onclick的控件时,会触发MainAbility下的这个函数
4.最后调用卡片控制器 WidgetImpl 中的onTriggerFormEvent()
3.list跳转事件
list组件只能添加一个onclick,而且在点击的同时还需要获取点击的是list列表中的哪一项,这个比较特殊。
这个坑折磨了我好久,最终我发现在index.json中,可以使用idx获取到hml页面list的元素变量和索引。但是在官方文档并没有找到相关的内容,尝试了很久才解决这个问题。之后的部分就和跳转事件一样了,使用Video页面解析url进行播放就可以了。
总结:解决了list的点击事件之后,才发现这歌控件真是好用。能用list还是list方便。
六、加载页面,保存Cookie
启动之后的页面主要是为了登录账号,因为大部分的API是需要登录之后才可以获取到的。
1.webview加载页面
在base/layout/ability_main.xml中添加webview组件,代码如下
然后在启动页面执行加载操作。但其实加载前需要先从数据库中提取cookie信息,这个接下来说。
2.Cookie的读取和保存类
com/liangzili/demos/utils/CookieUtils.java
七、偏好型数据库
数据库的操作主要是com/liangzili/demos/database/PreferenceDataBase.java 这个类。使用轻量级偏好型数据库,更符合我们这里的需求。
亮哥🐮🍺!!!
精彩!
楼主:B站研发人员,学着点!!
过来学习,太厉害了
吸 吸 吸 亮哥好猛!我是你的迷弟
🍺🍺
感谢支持啊
大佬,牛逼
开源精神!
6哇
这个开发者相当牛B,把卡片的特性发挥的淋漓尽致,值得很多人学习
我来了,学习学习!!!
安装完服务卡片空白怎么解决呢
有没有改包名
牛逼牛逼
感谢捧场
卡片功能,目前看介绍,应该是系统桌面使用。
问题:能在应用内部使用吗? 即应用主界面也是类似系统桌面的一个菜单列表,点击某个菜单跳转到具体功能页面,这种能按卡片功能实现吗?
鸿蒙应用的目标是原子化服务,而服务卡片是原子化服务的展现形式
在哪下载全量代码呢?楼主太厉害了。
https://gitee.com/liangzili/bilibili-cards