HarmonyOS - 服務卡片進階(一)
前言
看本文章之前需要先熟悉一下原子化服務特征和流程 ??HarmonyOS-5分鐘教會你原子化服務??
基本概念
服務卡片(以下簡稱“卡片”)是FA的一種界面展示形式,將FA的重要信息或操作前置到卡片,以達到服務直達,減少體驗層級的目的。
卡片常用于嵌入到其他應用(當前只支持系統應用)中作為其界面的一部分顯示,并支持拉起頁面,發送消息等基礎的交互功能。卡片使用方負責顯示卡片。
- 卡片提供方
開發者僅需作為卡片提供方進行服務卡片內容的開發,控制卡片實際顯示的內容、控件布局以及控件點擊事件
- 卡片使用方
顯示卡片內容的宿主應用,控制卡片在宿主中展示的位置。
- 卡片管理服務
用于管理系統中所添加卡片的常駐代理服務,包括卡片對象的管理與使用,以及卡片周期性刷新等。
說明
卡片使用方和提供方不要求常駐運行,在需要添加/刪除/請求更新卡片時,卡片管理服務會拉起卡片提供方獲取卡片信息。
服務卡片的運作機制
先上圖:
卡片管理服務包含以下模塊:
- 周期性刷新:在卡片添加后,根據卡片的刷新策略啟動定時任務周期性觸發卡片的刷新。
- 卡片緩存管理:在卡片添加到卡片管理服務后,對卡片的視圖信息進行緩存,以便下次獲取卡片時可以直接返回緩存數據,降低時延。
- 卡片生命周期管理:對于卡片切換到后臺或者被遮擋時,暫停卡片的刷新;以及卡片的升級/卸載場景下對卡片數據的更新和清理。
- 卡片使用方對象管理:對卡片使用方的RPC對象進行管理,用于使用方請求進行校驗以及對卡片更新后的回調處理。
- 通信適配層:負責與卡片使用方和提供方進行RPC通信。
- 卡片提供方包含以下模塊:
- 卡片服務:由卡片提供方開發者實現,開發者實現onCreateForm、onUpdateForm和onDeleteForm處理創建卡片、更新卡片以及刪除卡片等請求,提供相應的卡片服務。
- 卡片提供方實例管理模塊:由卡片提供方開發者實現,負責對卡片管理服務分配的卡片實例進行持久化管理。
- 通信適配層:由HarmonyOS SDK提供,負責與卡片管理服務通信,用于將卡片的更新數據主動推送到卡片管理服務。
服務卡片開發簡介
關于服務卡片的接口說明,Java卡片與JS卡片選型,約束與限制可以去官網上查看:
Java卡片開發
這次先來講解Java卡片開發,后期會專門用一篇來講解JS卡片開發。
使用DevEco Studio創建卡片工程(前面文章已經說明,這里不再累述)。
我們先看看配置文件config.json:
"forms": [
{
"landscapeLayouts": [
"$layout:form_weather_widget_2_2"
],
"isDefault": true,
"scheduledUpdateTime": "10:30",
"defaultDimension": "2*2",
"name": "widget",
"description": "This is a service widget",
"colorMode": "auto",
"type": "Java",
"supportDimensions": [
"2*2"
],
"portraitLayouts": [
"$layout:form_weather_widget_2_2"
],
"updateEnabled": true,
"updateDuration": 1
}
],
“type”: 默認值是JS,我們需要更改為“Java”代表是一個Java卡片。
“scheduledUpdateTime”: 表示卡片的定點刷新的時刻,采用24小時制,精確到分鐘。但是我在設置時間點的時候并沒有更新,具體原因待考察。
"scheduledUpdateTime": "10:30",
“updateEnabled”: 表示卡片是否支持周期性刷新,取值范圍:
- true:表示支持周期性刷。
- false:表示不支持周期性刷新。
“updateDuration”:表示卡片定時刷新的更新周期,單位為30分鐘,取值為自然數。
當取值為0時,表示該參數不生效。
當取值為正整數N時,表示刷新周期為30*N分鐘。
"updateEnabled": true,
"updateDuration": 1
設置卡片定時刷新,每30分鐘更新一次。
“supportDimensions”: 表示卡片支持的外觀規格,取值范圍:
- 1*2:表示1行2列的二宮格。
- 2*2:表示2行2列的四宮格。
- 2*4:表示2行4列的八宮格。
- 4*4:表示4行4列的十六宮格。
“portraitLayouts”:表示卡片外觀規格對應的豎向布局文件,與supportDimensions中的規格一一對應。
僅當卡片類型為Java卡片時,需要配置該標簽。
“landscapeLayouts”:表示卡片外觀規格對應的橫向布局文件,與supportDimensions中的規格一一對應。
僅當卡片類型為Java卡片時,需要配置該標簽。
2. MainAbility中覆寫卡片相關回調函數。
- onCreateForm(Intent intent)。
- onUpdateForm(long formId)。
- onDeleteForm(long formId)。
- onCastTempForm(long formId)。
- onEventNotify(Map formEvents)。
- onAcquireFormState(Intent intent)。
當卡片使用方請求獲取卡片時,卡片提供方會被拉起并調用onCreateForm(Intent intent)回調,intent中會帶有卡片ID,卡片名稱,臨時卡片標記和卡片外觀規格信息,代碼如下:
protected ProviderFormInfo onCreateForm(Intent intent) {
HiLog.info(TAG, "onCreateForm");
// 卡片id
long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);
// 卡片名稱
String formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);
// 卡片規格
int dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);
HiLog.info(TAG, "onCreateForm: formId=" + formId + ",formName=" + formName + ",dimension=" + dimension);
// 將卡片信息存入數據庫
saveFormInfo(formId, formName, dimension);
// 開發者需要根據卡片的名稱以及外觀規格獲取對應的xml布局并構造卡片對象,此處ResourceTable.Layout_form_weather_widget_2_2
ProviderFormInfo formInfo = new ProviderFormInfo(ResourceTable.Layout_form_weather_widget_2_2, this);
//獲取此 ProviderFormInfo 對象中包含的ComponentProvider數據。
ComponentProvider componentProvider = formInfo.getComponentProvider();
//設置組件的文本內容
componentProvider.setText(ResourceTable.Id_weather_text, "天氣:多云");
componentProvider.setText(ResourceTable.Id_weather_temperature, "溫度:29度");
componentProvider.setText(ResourceTable.Id_weather_ph, "PH值:2.9");
//將ComponentProvider中指定的操作合并到此ProviderFormInfo對象中包含的 ComponentProvider 對象中
formInfo.mergeActions(componentProvider);
return formInfo;
}
布局:form_weather_widget_2_2.xml。
<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#FFFFFFFF"
ohos:remote="true">
<Image
ohos:height="match_parent"
ohos:width="126vp"
ohos:horizontal_center="true"
ohos:image_src="$media:weather"
ohos:scale_mode="zoom_start"
ohos:top_margin="17vp"/>
<DirectionalLayout
ohos:height="match_content"
ohos:width="match_content"
ohos:align_parent_bottom="true"
ohos:bottom_margin="12vp"
ohos:horizontal_center="true"
ohos:orientation="vertical">
<Text
ohos:id="$+id:weather_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text="天氣:晴"
ohos:text_color="#E5000000"
ohos:text_size="12fp"
ohos:text_weight="400"
ohos:top_margin="2vp"
ohos:truncation_mode="ellipsis_at_end"/>
<Text
ohos:id="$+id:weather_temperature"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text="溫度:25度"
ohos:text_color="#99000000"
ohos:text_size="12fp"
ohos:text_weight="400"
ohos:top_margin="2vp"
ohos:truncation_mode="ellipsis_at_end"/>
<Text
ohos:id="$+id:weather_ph"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text="PH值:2.5"
ohos:text_color="#99000000"
ohos:text_size="12fp"
ohos:text_weight="400"
ohos:top_margin="2vp"
ohos:truncation_mode="ellipsis_at_end"/>
</DirectionalLayout>
</DependentLayout>
當需要卡片提供方更新數據時(如觸發了定時更新、定點更新或者卡片使用方主動請求更新),卡片提供方獲取最新數據,并調用updateForm接口更新卡片。示例如下:
protected void onUpdateForm(long formId) {
HiLog.info(TAG, "onUpdateForm");
super.onUpdateForm(formId);
refeshData();
}
/**
* update forms
*/
private void refeshData() {
// 獲取卡片集合
List<FormInfo> formList = DatabaseUtils.queryForms(this, null);
for (FormInfo formInfo : formList) {
ProviderFormInfo refesh = new ProviderFormInfo(ResourceTable.Layout_form_weather_widget_2_2, this);
ComponentProvider componentProvider = refesh.getComponentProvider();
//這里更新的值,實際使用中可根據自己項目要求設置,比如:隨機獲取一個值
componentProvider.setText(ResourceTable.Id_weather_text, "天氣:多云轉晴");
componentProvider.setText(ResourceTable.Id_weather_temperature, "溫度:30度");
componentProvider.setText(ResourceTable.Id_weather_ph, "PH值:3.0");
try {
//卡片提供方主動更新卡片
updateForm(formInfo.getFormId(), componentProvider);
} catch (FormException e) {
HiLog.error(TAG, "FormException");
}
}
}
定時更新效果:
總結
實際項目中需要通過網絡獲取數據,這里只是簡單的模擬數據。只是簡單說明了服務卡片創建的回調方法實現,定點和定時數據更新的時機和回調方法的實現,下期會更新關于服務卡片信息持久化、卡片控制事件。