鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程
一、基本概念
- 元服務(原名原子化服務)是一種基于HarmonyOS API的全新服務提供方式,以HarmonyOS萬能卡片等多種呈現形態(tài),向用戶提供更輕量化的服務。具有即用即走、信息外顯、服務直達的特性。
- 萬能卡片(簡稱卡片)是一種界面展示形式,可以將應用的重要信息或操作前置到卡片,以達到服務直達、減少體驗層級的目的。
- ArkUI框架是一套構建分布式應用界面的聲明式UI開發(fā)框架,其使用極簡的UI信息語法、豐富的UI組件、以及實時界面預覽工具,幫助開發(fā)者提升HarmonyOS應用界面開發(fā)效率。
- AppGallery Connect(簡稱AGC)致力于為應用的創(chuàng)意、開發(fā)、分發(fā)、運營、經營各環(huán)節(jié)提供一站式服務,構建全場景智慧化的應用生態(tài)體驗。
- 端云一體化是為豐富HarmonyOS對云端開發(fā)的支持、實現HarmonyOS生態(tài)端云聯動,DevEco Studio推出了云開發(fā)功能,開發(fā)者在創(chuàng)建工程時選擇云開發(fā)模板,即可在DevEco Studio內同時完成HarmonyOS應用/服務的端側與云側開發(fā)。
二、主要功能
本次開發(fā)的實用小工具主要功能有:
- 油價查詢,點擊城市列表之后,就可以查看當前城市的油價,包括92,95,98,柴油等。
- 垃圾分類查詢,輸入物品名稱就可以查看垃圾的詳細分類,而不再害怕垃圾分類出錯。
- 當前定位查看,我們可以很方便的知道自己當前的位置信息。
- 提供12,22,24,44卡片。
API版本:API9
應用包名:com.jianguo.utilitybox
三、項目初始化
- 當前未打開任何工程,單擊DevEco Studio歡迎頁中“Create Project”創(chuàng)建新工程。
- 當前已打開工程,單擊菜單欄“File > New > Create Project”創(chuàng)建新工程。
首先創(chuàng)建項目,選擇原子化服務,第四個模版端云一體化模版
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
點擊下一步:
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
這個時候我們需要為工程關聯云開發(fā)所需的資源,即在DevEco Studio中選擇您的華為開發(fā)者賬號加入的開發(fā)者團隊,將該團隊在AGC的同包名應用關聯到當前工程。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
然后我們點擊登陸就好。
這個時候會來到下面的授權頁面,我們點擊允許就可以。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
單擊“AppGallery Connect”打開AGC應用創(chuàng)建向導,填寫應用信息,單擊“確認”按鈕創(chuàng)建應用。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
我們點擊箭頭這兒就會跳轉到我們的。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
agc頁面。這個時候我們選擇創(chuàng)建項目,然后再創(chuàng)建應用。我之前已經有項目了。所以我們直接在項目里創(chuàng)建應用就可以。
比如我這里就選擇。
下面這個就可以。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
然后就會跳轉到設置位置處理頁面。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
我們點擊下一步就會到下面的添加應用界面,然后我們只需要填寫應用名稱就可以,其他的都會默認,如果默認失敗的話,我們就設置應用包名:com.jianguo.utilitybox。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
然后確定。
這個時候就會有恭喜您!
應用創(chuàng)建已完成。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
我們選擇前往控制臺,然后來到Severless這一塊。把我們需要的認證服務,云函數,云數據庫,云緩存,云存儲,統統打開。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
我們回到IDE繼續(xù)開發(fā),點擊Finsh就可。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
出現這個,我們ok就可以。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
然后大家可以看到工程配置完成。
成功創(chuàng)建工程并關聯云開發(fā)資源后,DevEco Studio會為工程自動執(zhí)行一些初始化配置,并開通云開發(fā)相關服務:認證服務、云函數、云數據庫、云托管、API網關、云存儲。,所以上面我們在控制臺的操作其實也可以不用操作。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
端側工程自動集成AGC SDK,包括AGC SDK 配置文件entry/src/main/resources/rawfile/agconnect-services.json 和在entry/oh-package.json5配置文件中引入的AGC相關云服務最新版本SDK。
"dependencies": {
"@hw-agconnect/crypto-ohos": "^1.0.10",
"@hw-agconnect/function-ohos": "^1.0.10",
"@hw-agconnect/auth-ohos": "^1.0.10",
"@hw-agconnect/cloudstorage-ohos": "^1.0.10",
"@hw-agconnect/api-ohos": "^1.0.10",
"@hw-agconnect/base-ohos": "^1.0.10",
"@hw-agconnect/core-ohos": "^1.0.10",
"@hw-agconnect/credential-ohos": "^1.0.10",
"@ohos/agconnect-auth-component": "^1.0.5",
"long": "5.2.1"
}
云側工程自動集成云數據庫最新版本Node.js Server SDK。
/Users/jianguo/Desktop/teaching/utilitybox/CloudProgram/cloudfunctions/idgenerator/package.json
"dependencies": {
"@agconnect/database-server": "^1.0.7"
}
}
四、端云一體化開發(fā)
大家都知道我這次用的是端云一體化開發(fā),那那么我們就有必要來了解一下端云協同的目錄結構
端云一體化開發(fā)工程目錄分為三個子工程:如下圖所示:
- 端開發(fā)工程(Application)。
- 云開發(fā)工程(CloudProgram)。
- 端側公共庫(External Libraries)。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
1、端開發(fā)工程(Application)
端開發(fā)工程主要用于開發(fā)應用端側的業(yè)務代碼,端開發(fā)工程目錄結構如下:
端側的目錄和之前大家看到的文件目錄結構都差不多
- Application
- AppScope
app.json5 // 應用的全局配置信息
- entry // 應用/服務模塊,編譯構建生成一個HAP
oh_modules // 用于存放三方庫依賴信息
- src/main
- ets // 用于存放ArkTS源碼
- resources // 用于存放應用/服務所用到的資源文件
module.json5 // Stage模型配置文件
build-profile.json5 // 當前模塊信息、編譯信息配置項
hvigorfile.ts // 模塊級編譯構建任務腳本
oh-package.json5 // 配置三方包聲明的入口及包名
build-profile.json5 // 應用配置信息,包括簽名、產品配置等
hvigorfile.ts // 應用級編譯構建任務腳本
2、云開發(fā)工程(CloudProgram)
云開發(fā)工程中開發(fā)者可以為應用開發(fā)云函數和云數據庫服務資源,云開發(fā)工程目錄結構如下:
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
- CloudProgram
- clouddb // 云數據庫工程目錄
dataentry // 用于存放數據條目文件
objecttype // 用于存放對象類型文件
db-config.json // 模塊配置文件
- cloudfunctions // 云函數工程目錄
node_modules // 包含所有三方依賴
cloud-config.json // 云開發(fā)工程配置文件
package.json // 定義了TypeScript公共依賴
五、云函數開發(fā)指南
1、創(chuàng)建函數
在云端工程(CloudProgram)中可以創(chuàng)建函數、編寫函數業(yè)務代碼、為函數配置調用觸發(fā)器。
單擊“cloudfunctions”目錄,選擇“New > Cloud Function”創(chuàng)建云函數。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
輸入函數名稱,單擊“OK”按鈕DevEco Studio自動生成函數目錄。函數名稱僅支持小寫英文字母、數字、中劃線(-),首字母必須為小寫字母,結尾不能為中劃線(-)。
比如add。
云函數目錄結構。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
- add
node_modules // 自動為該函數引入依賴包
function-config.json // 函數的配置文件,可配置觸發(fā)器,通過觸發(fā)器暴露的觸發(fā)條件來實現函數調用。
package.json // 包含了當前函數的名稱、版本等函數元數據。
add.ts // 函數入口文件
云函數觸發(fā)器。
云函數觸發(fā)器在function-config.json文件中triggers屬性中配置,當前支持HTTP觸發(fā)器、CLOUDDB觸發(fā)器、AUTH觸發(fā)器、CLOUDSTORAGE觸發(fā)器、CRON觸發(fā)器五種。
- HTTP觸發(fā)器工程創(chuàng)建完成后默認自動在function-config.json文件生成HTTP觸發(fā)器配置。函數部署到云端后會自動生成觸發(fā)URL,開發(fā)者向URL發(fā)起HTTP請求時觸發(fā)函數。
{
"handler": "IdGenerator.myHandler",
"triggers": [
{
"type": "http",
"properties": {
"enableUrlDecode": true,//通過HTTP觸發(fā)器觸發(fā)函數,對于contentType為“application/x-www-form-urlencoded”的觸發(fā)請求,是否使用URLDecoder對請求body進行解碼再轉發(fā)到函數中。true:啟用。false:不啟用。
"authFlag": "true",//是否鑒權,默認為true。
"authAlgor": "HDA-SYSTEM",//鑒權算法,默認為HDA-SYSTEM。
"authType": "apigw-client",//HTTP觸發(fā)器的認證類型。apigw-client:端側網關認證,適用于來自APP客戶端側的函數調用。 cloudgw-client:云側網關認證,適用于來自APP服務器側的函數調用
"mode": "NO_PATH"
}
}
]
}
2、開發(fā)云函數
云函數的代碼實現基于不同的語言運行環(huán)境可分為Node.js、Java、Python,還有一種比較特別運行環(huán)境為Custom Runtime(自定義運行環(huán)境)。本工程的語言運行環(huán)境為Node.js。
云函數的入口方法:
module.exports.myHandler = function(event, context, callback, logger)。
- myHandler:入口方法名稱。
- event:調用方傳遞的事件對象,JSON格式。
- context:函數運行時上下文對象,封裝了日志接口、回調接口、環(huán)境變量env對象等。
- callback:事件處理結果。
- logger:記錄日志。開發(fā)者在代碼中使用logger接口記錄日志,當前支持四種級別。
- logger.debug()
- logger.error()
- logger.warn()
- logger.info()
函數必須通過顯示調用callback(object)將事件處理結果返回給AGC,結果可以是任意對象,但必須與JSON.stringify兼容,AGC會將結果轉換成JSON字符串,返回給調用方。callback執(zhí)行完成后,函數即執(zhí)行結束。
為云函數添加返回內容。
let myHandler = async function (event, context, callback, logger) {
logger.info(event);
// do something here
callback({
code: 0,
desc: "Success."
});
};
export { myHandler };
調試云函數 函數開發(fā)過程中,開發(fā)者可在本地進行調試,或者將函數部署到AGC云端后,在本地觸發(fā)調用云端函數。當前本地調試支持Run和Debug兩種模式,Debug模式支持使用斷點來追蹤函數的運行情況。
- 本地云函數調試,單擊"cloudfunctions > Run/Debug Cloud Function"運行/調試云函數。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
查看Run面板,若出現“Cloud Functions loaded successfully”,標識云函數啟動成功(云函數啟動/調試將部署cloudfunctions中所有的云函數),并生成對應的POST URL。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
在菜單欄選擇“Tools > CloudDev > Cloud Functions Requestor”觸發(fā)云函數調用。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
在彈出的云函數調用界面填寫觸發(fā)事件參數。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
- Environment:選擇函數調用環(huán)境,Local表示本地調用,Remote表示遠程調用(需要先將函數部署到AGC云端)。
- Cloud Function:選擇需要觸發(fā)的云函數。
- Event:輸入事件參數,內容為JSON格式請求體數據。
單擊Trigger按鈕,觸發(fā)執(zhí)行云函數,執(zhí)行結果展示在Result框內,Run面板同時打印運行日志。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
部署云函數 完成函數代碼開發(fā)后,開發(fā)者可將函數部署到AGC控制臺,支持單個部署和批量部署。
- 右鍵單擊需要部署的函數目錄,選擇“Deploy Cloud Functions”。
- 底部狀態(tài)欄右側將顯示函數打包與部署進度,直至出現“Deploy successfully”消息表示函數部署成功。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
登錄AGC控制臺,進入當前項目的云函數服務菜單,可查看開發(fā)者部署的函數。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
遠程函數測試 在“Cloud Functions Reuestor”面板中,更改Environment為Remote遠程調用,單擊“Trigger”按鈕,在Result中顯示返回結果。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
當開發(fā)者創(chuàng)建的函數或函數別名中創(chuàng)建一個HTTP類型的觸發(fā)器后,在應用客戶端調用函數時需要傳入HTTP觸發(fā)器的標識,查詢方法如下: 在函數的觸發(fā)器頁面點擊“HTTPTrigger”觸發(fā)器,查看“觸發(fā)URL”的后綴,獲取觸發(fā)器標識,格式為“函數名-版本號”。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
3、調用云函數
應用集成云函數SDK后,可以在應用內直接通過SDK API調用AGC中的云函數,云函數SDK與AGC的函數調用基于HTTPS的安全訪問。
- 在端側應用(Application)中“entry > src/main/ets > services”目錄創(chuàng)建
SudokuAlgorithmFunction.ts
文件,編寫調用云函數方法。
Button('請求自定義云函數')
.fontSize(16)
.onClick(() => {
getSudokuPuzzle(getContext(this)).then((ret) => {
Log.info(Constants.LOG_TAG_NAME, `單擊按鈕調用云函數返回結果: ${JSON.stringify(ret)}`)
})
})
然后我們簽名,在真機中。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
六、華為認證服務
當前AGC認證服務為HarmonyOS應用/服務提供的登錄認證方式有手機、郵箱和關聯賬號三種方式。本工程使用“郵箱+驗證碼”的方式作為應用的登錄入口。我們這次使用的是手機號碼登錄。
需要在AGC控制臺開通認證服務(工程創(chuàng)建時默認開通),并在“認證方式”頁簽中啟用“郵箱地址”。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
調用PhoneUserBuilder生成PhoneUser,然后調用PhoneAuthProvider.credentialWithVerifyCode注冊用戶。注冊成功后,系統會自動登錄,無需再次調用登錄接口。也可以使用signIn登錄接口,通過第三方認證來登錄AGConnect平臺,在entry/src/main/ets/services/Auth.ts認證工具類中添加郵箱賬號注冊用戶方法。
public async login(countryCode: string, phoneNumber: string, verifyCode: string): Promise<AgUser> {
return new Promise((resolve, reject) => {
const credential = PhoneAuthProvider.credentialWithVerifyCode(countryCode, phoneNumber, verifyCode);
this.agc.auth().signIn(credential).then(async (ret) => {
Log.info(TAG, "User has signed in..");
// @ts-ignore
let user = ret.getUser();
let userExtra = await ret.getUser().getUserExtra();
let loginRes = new AgUser(
user.getUid(),
user.getPhotoUrl(),
user.getPhone(),
user.getDisplayName(),
userExtra.getCreateTime(),
userExtra.getLastSignInTime())
resolve(loginRes);
}).catch((error) => {
Log.error(TAG, "Error: ", error);
reject(error);
});
});
}
1、構建手機登錄頁面
通過容器組件Flex、Row、Column以及基礎組件Text、Image、Button、Navigation、TextInput,構建手機驗證碼登錄頁面。
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text($r('app.string.auth_dialog_title'))
.fontSize($r('app.float.navigation_font_size'))
.margin({ bottom: Constants.LENGTH_20_PX })
Flex({ direction: FlexDirection.Row }) {
Select(mockData)
.font({ size: $r('app.float.body_font_size') })
.selectedOptionFont({ size: $r('app.float.body_font_size') })
.optionFont({ size: $r('app.float.body_font_size') })
.value(this.countryCode)
.layoutWeight(Constants.LENGTH_1_PX)
.backgroundColor($r('app.color.placeholder_background'))
.borderRadius(Constants.BORDER_RADIUS_4_PX)
.height(Constants.HEIGHT_40)
.onSelect((_, val) => {
this.countryCode = val.substring(0, val.length - 4);
})
TextInput({ placeholder: $r('app.string.auth_dialog_number_placeholder') })
.layoutWeight(Constants.LENGTH_3_PX)
.margin({ left: Constants.LENGTH_5_PX })
.borderRadius(Constants.BORDER_RADIUS_4_PX)
.maxLength(Constants.LENGTH_20_PX)
.height(Constants.HEIGHT_40)
.enabled(this.timer === 60)
.onChange((val) => {
this.phoneNumber = val;
})
}
.margin({ bottom: Constants.LENGTH_20_PX })
Flex({ direction: FlexDirection.Row }) {
TextInput({ placeholder: $r('app.string.auth_dialog_code_placeholder'), text: this.verificationCode })
.layoutWeight(Constants.LENGTH_3_PX)
.margin({ right: Constants.LENGTH_5_PX })
.borderRadius(Constants.BORDER_RADIUS_4_PX)
.maxLength(Constants.LENGTH_6_PX)
.height(Constants.HEIGHT_40)
.onChange((val) => {
this.verificationCode = val;
})
Button(this.timer === 60 ? $r('app.string.auth_dialog_get_code_button_text') : this.timer.toString(), {
type: ButtonType.Normal
})
.backgroundColor($r('app.color.start_window_background'))
.layoutWeight(Constants.LENGTH_2_PX)
.borderColor($r('app.color.action_button_background'))
.borderWidth(Constants.LENGTH_1_PX)
.fontColor($r('app.color.action_button_background'))
.borderRadius(Constants.BORDER_RADIUS_4_PX)
.margin({ left: Constants.LENGTH_5_PX })
.height(Constants.HEIGHT_40)
.enabled(this.canGetCode() && this.timer === 60)
.onClick(() => this.onGetCodeButtonClicked())
}
.margin({ bottom: Constants.LENGTH_20_PX })
Button($r('app.string.auth_dialog_auth_button_text'), { type: ButtonType.Normal })
.width(Constants.PERCENT_100)
.borderRadius(Constants.BORDER_RADIUS_4_PX)
.backgroundColor($r('app.color.action_button_background'))
.enabled(this.canAuthorize() && this.verificationCode.length > 5 && this.canLogin)
.opacity(this.canLogin ? 1 : 0.5)
.height(Constants.HEIGHT_40)
.onClick(() => this.onAuthButtonClicked())
}
.height(Constants.PERCENT_50)
.padding({ right: Constants.LENGTH_20_PX, left: Constants.LENGTH_20_PX })
}
2、用戶登錄成功信息寫入緩存
調用自定義的登錄接口實現登錄,并使用首選項自定義工具接口將用戶信息寫入緩存。,這樣下次進入之后,就可以進行對應的邏輯判斷。執(zhí)行對應的流程。
onAuthButtonClicked() {
this.canLogin = false;
this.agcAuth.login(this.countryCode, this.phoneNumber, this.verificationCode).then(user => {
AppStorage.Set<AgUser>('user', user);
PreferencesUtil.putPreference(getContext(this), Constants.USER_AUTH_INFO, JSON.stringify(user));
Log.info(TAG, "Logged in succesfully.");
this.canLogin = true;
router.replaceUrl({
url: "pages/MainPage"
})
}).catch((err) => {
this.canLogin = true;
Log.error(TAG, "Logged in failed " + JSON.stringify(err));
AlertDialog.show({
title: $r('app.string.common_prompt'),
message: $r('app.string.common_login_fail'),
});
});
}
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
七、元服務開發(fā)
元服務 (原為"原子化服務") 是一種基于HarmonyOS API的全新服務提供方式,以鴻蒙萬能卡片等多種呈現形態(tài), 向用戶提供更輕量化的服務。具有即用即走、信息外顯、服務直達的特性。
萬能卡片(以下簡稱“卡片”)是一種界面展示形式,可以將應用的重要信息或操作前置到卡片,以達到服務直達、減少體驗層級的目的??ㄆS糜谇度氲狡渌麘茫ó斍翱ㄆ褂梅街恢С窒到y應用,如桌面)中作為其界面顯示的一部分,并支持拉起頁面、發(fā)送消息等基礎的交互功能。
下面是我們開發(fā)卡片時候的實現原理
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
這里涉及的幾個知識點給大家介紹一下
- 卡片使用方:顯示卡片內容的宿主應用,控制卡片在宿主中展示的位置。
- 卡片提供方:提供卡片顯示內容的應用,控制卡片的顯示內容、控件布局以及控件點擊事件。
- 卡片管理服務:用于管理系統中所添加卡片的常駐代理服務。
- 卡片渲染服務:用于管理卡片渲染實例,渲染實例與卡片使用方上的卡片組件一一綁定。
ArkTS卡片提供了postCardAction()接口用于卡片內部和提供方應用間交互,當前支持router、message和call三種類型的事件,僅在卡片中可以調用。這個我們在查詢油價,以及處理message跳轉的時候會用到。大家繼續(xù)往后看就可以。
1、油價查詢(2*2)
這里我們需要學習的知識點在于卡片的創(chuàng)建,以及卡片數據如何交互。
創(chuàng)建ArkTS卡片有兩種方式:
- 通過在”entry“目錄右鍵單擊“New > Service Widget”創(chuàng)建卡片。
- 通過在”entry > src/main/ets > widget > pages“目錄右鍵單擊“New > ArkTS File”創(chuàng)建文件,并在卡片配置文件form_config.json中配置卡片信息。
使用第二種方式創(chuàng)建卡片,在”entry > src/main/ets > widget > pages“目錄右鍵單擊“New > ArkTS File”創(chuàng)建RubbishWidgetCard.ets
文件,接著打開"entry > src/main/resources > base > profile"目錄下的form_config.json
文件,配置名稱為rubbish
的2*2卡片
這樣的話,我們的卡片就算創(chuàng)建完成了,
Column() {
Row() {
Image($r("app.media.rubbish")).width(this.Image_WIDTH_PERCENT).margin({
right: 5
})
Text(this.TITLE)
.fontSize($r('app.float.font_size'))
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.item_title_font'))
}
}
.width(this.FULL_WIDTH_PERCENT)
.backgroundColor($r("app.color.emuiLow4_alpha"))
.height(this.FULL_HEIGHT_PERCENT)
.justifyContent(FlexAlign.Center)
.onClick(() => {
postCardAction(this, {
"action": this.ACTION_TYPE,
"abilityName": this.ABILITY_NAME,
"params": {
"targetPage": this.MESSAGE
}
});
})
}
但是要實現卡片數據的更新。
ArkTS卡片框架提供了updateForm()接口和requestForm()接口主動觸發(fā)卡片的頁面刷新。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
接口 | 是否系統能力 | 約束 |
updateForm | 否 | 1. 提供方調用。 2. 提供方僅允許刷新自己的卡片,其他提供方的卡片無法刷新。 |
requestForm | 是 | 1. 使用方調用。 2. 僅允許刷新添加到當前使用方的卡片,添加到其他使用方的卡片無法刷新。 |
卡片中需要使用@LocalStorageProp裝飾器接收。
@LocalStorageProp("puzzles") puzzles: Array<Array<number>> = [];
@LocalStorageProp("answers") answers: Array<Array<Array<number>>> = [];
然后,我們以更新深圳的天氣為例,在/src/main/ets/entryformability/EntryFormAbility.ts寫寫對應的請求事件。
upData(formId :string){
let formInfo = formBindingData.createFormBindingData({
'text': '刷新中...'
})
formProvider.updateForm(formId, formInfo)
console.info('Result:的結果' + JSON.stringify(formId));
let httpRequest = http.createHttp();
httpRequest.request(Constants.OILSERVER, {
method: http.RequestMethod.GET,
readTimeout: Constants.HTTP_READ_TIMEOUT,
connectTimeout: Constants.HTTP_READ_TIMEOUT
, extraData: {
'province': "深圳",
'app_id': Constants.APPID,
'app_secret': Constants.APPSECRET
},
}, (err, data) => {
if (!err) {
// data.result為HTTP響應內容,可根據業(yè)務需要進行解析
console.info('Result:的結果' + JSON.stringify(data.result));
let OilModel: OilModel = JSON.parse(data.result.toString())
// 注意:FormExtensionAbility在觸發(fā)生命周期回調時被拉起,僅能在后臺存在5秒
// 建議下載能快速下載完成的小文件,如在5秒內未下載完成,則此次網絡圖片無法刷新至卡片頁面上
let formData = {
'oil': OilModel.data,
'loaded': true,
"time": getTime()
};
let formInfo = formBindingData.createFormBindingData(formData)
formProvider.updateForm(formId, formInfo).then((data) => {
console.info('FormAbility updateForm success.' + JSON.stringify(data));
}).catch((error) => {
console.error('FormAbility updateForm failed: ' + JSON.stringify(error));
})
// 當該請求使用完畢時,調用destroy方法主動銷毀
httpRequest.destroy();
} else {
console.info('error:' + JSON.stringify(err));
// 取消訂閱HTTP響應頭事件
httpRequest.off('headersReceive');
// 當該請求使用完畢時,調用destroy方法主動銷毀
httpRequest.destroy();
}
}
);
}
然后我們在onUpdateForm中去調用就可以啦。
onUpdateForm(formId) {
this.upData(formId)
// Called to notify the form provider to update a specified form.
}
這樣我們就完成了對油價的查詢。
這里我們主要了解的就是對卡片事件能力的處理。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
接口定義:postCardAction(component: Object, action: Object): void
接口參數說明:
參數名 | 參數類型 | 必填 | 參數描述 |
component | Object | 是 | 當前自定義組件的實例,通常傳入this。 |
action | Object | 是 | action的具體描述,詳情見下表。 |
action參數說明:
Key | Value | 樣例描述 |
“action” | string | action的類型,支持三種預定義的類型: - “router”:跳轉到提供方應用的指定UIAbility。 - “message”:自定義消息,觸發(fā)后會調用提供方FormExtensionAbility的onFormEvent()生命周期回調。 - “call”:后臺啟動提供方應用。觸發(fā)后會拉起提供方應用的指定UIAbility(僅支持launchType為singleton的UIAbility,即啟動模式為單實例的UIAbility),但不會調度到前臺。提供方應用需要具備后臺運行權限(ohos.permission.KEEP_BACKGROUND_RUNNING)。 |
“bundleName” | string | “router” / “call” 類型時跳轉的包名,可選。 |
“moduleName” | string | “router” / “call” 類型時跳轉的模塊名,可選。 |
“abilityName” | string | “router” / “call” 類型時跳轉的UIAbility名,必填。 |
“params” | Object | 當前action攜帶的額外參數,內容使用JSON格式的鍵值對形式?!癱all” 類型時需填入參數’method’,且類型需要為string類型,用于觸發(fā)UIAbility中對應的方法,必填。 |
(1)通過message事件刷新卡片內容
實現功能:在卡片上實現當前城市的油價查詢,在頁面里實現對各個城市油價的查詢
主要技術,通過message事件刷新卡片內容,在卡片頁面中可以通過postCardAction接口觸發(fā)message事件拉起FormExtensionAbility,然后由FormExtensionAbility刷新卡片內容,展示油價信息
.onClick(() => {
postCardAction(this, {
'action': 'message',
'params': {
'info': 'refreshImage'
}
});
})
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
2、垃圾分類(1*2)
這里實現的功能是點擊卡片之后,進入垃圾分類查詢頁的詳情。輸入物品名稱。就可以查看具體的垃圾分類信息。
(1)使用router事件跳轉到指定UIAbility
.onClick(() => {
postCardAction(this, {
'action': 'router',
'abilityName': 'EntryAbility',
"params": {
"targetPage": this.MESSAGE
}
});
})
然后我們在src/main/ets/entryability/EntryAbility.ts中處理對應的邏輯。
onCreate(want) {
console.info("onCreate want:" + JSON.stringify(want));
if (want.parameters.params !== undefined) {
let params = JSON.parse(want.parameters.params);
hilog.info(0x0000, 'tonCreate router targetPage', '%{public}s', params.targetPage)
console.info("onCreate router targetPage:" + params.targetPage);
selectPage = params.targetPage;
}
}
如果UIAbility已在后臺運行,在收到Router事件后會觸發(fā)onNewWant生命周期回調。
onNewWant(want, launchParam) {
console.info("onNewWant want:" + JSON.stringify(want));
if (want.parameters.params !== undefined) {
let params = JSON.parse(want.parameters.params);
hilog.info(0x0000, 'tonCreate router targetPage', '%{public}s', params.targetPage)
console.info("onNewWant router targetPage:" + params.targetPage);
console.info("獲取的 params.targetPage是" + params.targetPage);
if (params.dimension !== undefined && params.dimension != null) {
AppStorage.Set<string>('message', params.dimension);
console.info("保存的 params.targetPage是" + params.targetPage);
}
selectPage = params.targetPage;
}
if (currentWindowStage != null) {
this.onWindowStageCreate(currentWindowStage);
}
}
根據傳遞的targetPage不同,選擇拉起不同的頁面。
onWindowStageCreate(windowStage: Window.WindowStage) {
let targetPage;
switch (selectPage) {
case "MainPage":
targetPage = "pages/MainPage";
break;
default:
targetPage = 'pages/LoginPage';
}
if (currentWindowStage === null) {
currentWindowStage = windowStage;
}
windowStage.loadContent(targetPage, (err, data) => {
if (err && err.code) {
console.info('Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
});
}
這樣我們就完成了跳轉。
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
3、當前定位(2*2)
點擊卡片之后,進入定位展示的詳情頁,展示當前的詳細定位。
主要技術,動態(tài)權限的獲取。
(1)動態(tài)權限獲取
首先需要在module.json中聲明對應權限
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.MEDIA_LOCATION",
},
{
"name": 'ohos.permission.APPROXIMATELY_LOCATION'
},
{
"name": 'ohos.permission.LOCATION'
}
],
然后在ets/entryability/EntryAbility.ts中添加動態(tài)權限的申請。
let AtManager = abilityAccessCtrl.createAtManager();
AtManager.requestPermissionsFromUser(this.context, [ 'ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION']).then((data) => {
hilog.info(0x0000, 'testTag', '%{public}s', 'request permissions from user success' + data);
}).catch((err) => {
hilog.error(0x0000, 'testTag', 'Failed to request permissions from user. Cause: %{public}s', JSON.stringify(err) ?? '');
});
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
然后我們編寫卡片代碼。
Column() {
Text("你想知道")
.fontSize($r('app.float.title_immersive_font_size'))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r('app.color.text_font_color'))
.maxLines(this.MAX_LINES)
Text("你當前的位置嗎")
.fontSize("14fp")
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r('app.color.text_font_color'))
.maxLines(this.MAX_LINES)
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.padding($r('app.float.column_padding'))
.width(this.FULL_WIDTH_PERCENT)
.height(this.FULL_HEIGHT_PERCENT)
.backgroundColor($r('app.color.emuiLow2_alpha'))
.onClick(() => {
postCardAction(this, {
"action": this.ACTION_TYPE,
"abilityName": this.ABILITY_NAME,
"params": {
"targetPage": this.MESSAGE
}
});
})
}
運行之后的效果:
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
鴻蒙入門開發(fā)教程:一文帶你詳解工具箱元服務的開發(fā)流程-開源基礎軟件社區(qū)
八、總結
本文我們從元服務的基本概念,到我們實用小工具的項目開發(fā),技術剝析,完整的了解了端元一體化開發(fā)元服務,以及如何在元服務中集成華為認證服務,到最后完成油價查詢功能在卡片上及時顯示,定位在卡片上實時刷新。以及點擊卡片分類,還可以進入詳情頁查詢更多物品的垃圾屬性,以及動態(tài)權限的獲取。
你可以學到的有:
- 了解元服務的基本概念
- 使用端云一體化開發(fā)、開發(fā)云函數、開發(fā)云數據庫,集成華為認證服務。
- 使用FormExtensionAbility創(chuàng)建、更新、刪除元服務卡片。
- 使用router、message和call三種類型的事件,處理對應邏輯。
也可點擊元服務官網,了解更多信息。