1、程序介紹
本示例主要展示了公共事件相關(guān)的功能,實現(xiàn)了一個檢測用戶部分行為的應(yīng)用。
具體而言,本案例實現(xiàn)了如下幾個公共事件功能:
通過訂閱系統(tǒng)公共事件,實現(xiàn)對用戶操作行為(亮滅屏、斷聯(lián)網(wǎng))的監(jiān)測;
通過在用戶主動停止監(jiān)測行為時發(fā)布自定義有序公共事件,實現(xiàn)對用戶主動觸發(fā)監(jiān)聽行為的持久化記錄;
通過在用戶設(shè)置對某一事件的監(jiān)聽狀態(tài)時發(fā)布粘性事件,記錄下本次應(yīng)用運行期間允許監(jiān)聽的事件列表,同時在應(yīng)用退出時將臨時允許的修改為不允許。
具體而言,本案例實現(xiàn)如下幾個界面:
進(jìn)入應(yīng)用顯示菜單頁,可選擇“進(jìn)入”,“歷史”,“設(shè)置”及“關(guān)于”幾個選項。
點擊“進(jìn)入”后跳轉(zhuǎn)至主頁面,點擊主頁面“開始監(jiān)控”按鈕,將開始監(jiān)聽系統(tǒng)公共事件,并進(jìn)行計時,此時按鈕內(nèi)容變更為“停止監(jiān)聽”;點擊停止監(jiān)聽按鈕,頁面上將顯示本次監(jiān)聽時長及監(jiān)聽期間收到的干擾信息匯總,并在頁面右下角顯示“查看詳情”按鈕,點擊按鈕將跳轉(zhuǎn)至詳情頁,顯示監(jiān)聽期間收到的干擾信息,應(yīng)用當(dāng)前僅監(jiān)聽了亮滅屏、斷聯(lián)網(wǎng)等用戶可操作的系統(tǒng)公共事件,后續(xù)可根據(jù)需求快速擴展。
返回至應(yīng)用菜單頁面,點擊“歷史”可查看用戶操作監(jiān)聽的歷史記錄,當(dāng)前支持每次運行期間最多存儲20條歷史記錄,超過20條后將刪除歷史數(shù)據(jù)。
返回至應(yīng)用菜單頁面,點擊“設(shè)置”可進(jìn)行具體系統(tǒng)事件的監(jiān)聽配置,應(yīng)用提供了“一直”、“僅本次”及“從不”三個選項,其中“僅本次”選項是指本次應(yīng)用運行期間將監(jiān)聽特定系統(tǒng)公共事件,應(yīng)用退出后該選項將自動調(diào)整為“從不”。
返回值應(yīng)用菜單頁面,點擊“關(guān)于”可查看應(yīng)用版本信息及本示例的說明。
本案例已在OpenHarmony凌蒙派-RK3568開發(fā)板驗證通過
2、知識準(zhǔn)備
2.1、commonEvent模塊
OpenHarmony通過CES(Common Event Service,公共事件服務(wù))為應(yīng)用程序提供訂閱、發(fā)布、退訂公共事件的能力。
公共事件從系統(tǒng)角度可分為:系統(tǒng)公共事件和自定義公共事件。
系統(tǒng)公共事件:CES內(nèi)部定義的公共事件,只有系統(tǒng)應(yīng)用和系統(tǒng)服務(wù)才能發(fā)布,例如HAP安裝,更新,卸載等公共事件。目前支持的系統(tǒng)公共事件詳見系統(tǒng)公共事件列表。
自定義公共事件:應(yīng)用自定義一些公共事件用來實現(xiàn)跨進(jìn)程的事件通信能力。
公共事件按發(fā)送方式可分為:無序公共事件、有序公共事件和粘性公共事件。
無序公共事件:CES轉(zhuǎn)發(fā)公共事件時,不考慮訂閱者是否接收到,按訂閱者訂閱先后順序轉(zhuǎn)發(fā)。
有序公共事件:CES轉(zhuǎn)發(fā)公共事件時,按訂閱者訂閱先后順序,在接收到前一個訂閱者回復(fù)后,再轉(zhuǎn)發(fā)下一個訂閱者。
粘性公共事件:能夠讓訂閱者收到在訂閱前已經(jīng)發(fā)送的公共事件就是粘性公共事件。普通的公共事件只能在訂閱后發(fā)送才能收到,而粘性公共事件的特殊性就是可以先發(fā)送后訂閱。發(fā)送粘性事件必須是系統(tǒng)應(yīng)用或系統(tǒng)服務(wù),且需要申請ohos.permission.COMMONEVENT_STICKY權(quán)限。
每個應(yīng)用都可以按需訂閱公共事件,訂閱成功,當(dāng)公共事件發(fā)布時,系統(tǒng)會將其發(fā)送給對應(yīng)的應(yīng)用。這些公共事件可能來自系統(tǒng)、其他應(yīng)用和應(yīng)用自身。
2.1.1、引入commonEvent模塊
import commonEvent from '@ohos.commonEvent';
2.1.2、commonEvent函數(shù)
declare namespace commonEvent {
function publish(event: string, callback: AsyncCallback<void>): void;
function publish(event: string, options: CommonEventPublishData, callback: AsyncCallback<void>): void;
function publishAsUser(event: string, userId: number, callback: AsyncCallback<void>): void;
function publishAsUser(event: string, userId: number, options: CommonEventPublishData, callback: AsyncCallback<void>): void;
function createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback<CommonEventSubscriber>): void;
function createSubscriber(subscribeInfo: CommonEventSubscribeInfo): Promise<CommonEventSubscriber>;
function subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback<CommonEventData>): void;
function unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback<void>): void;
}
其中,參數(shù)定義如下:
publish:發(fā)送公共事件,event 表示事件名稱。
publishAsUser:發(fā)送指定用戶的公共事件。
createSubscriber:創(chuàng)建事件的訂閱者。
subscribe:訂閱事件,可以是公共事件,也可以是自定義事件。
unsubscribe:取消訂閱事件,一旦取消,后續(xù)對的事件將不再接收。
2.1.3、創(chuàng)建訂閱者
function createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback<CommonEventSubscriber>): void;
function createSubscriber(subscribeInfo: CommonEventSubscribeInfo): Promise<CommonEventSubscriber>;
以異步方法構(gòu)造CommonEventSubscriber對象,創(chuàng)建公共事件訂閱者對象,使用callback形式返回。
其中,參數(shù)定義如下:
參數(shù)名 | 類型 | 必填 | 說明 |
---|---|---|---|
subscribeInfo | CommonEventSubscribeInfo | 是 | 公共事件訂閱者信息 |
callback | AsyncCallback | 是 | 事件監(jiān)聽回調(diào)函數(shù),當(dāng)收到訂閱的事件時,回調(diào)訂閱的事件數(shù)據(jù) |
2.1.4、開啟訂閱事件
function subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback<CommonEventData>): void;
以異步方法訂閱公共事件,使用callback形式返回。在調(diào)用subscriber接口訂閱公共事件前,需要先通過createSubscriber接口創(chuàng)建一個CommonEventSubscriber對象。
其中,參數(shù)定義如下:
參數(shù)名 | 類型 | 必填 | 說明 |
---|---|---|---|
subscribeInfo | CommonEventSubscribeInfo | 是 | 公共事件訂閱者信息 |
callback | AsyncCallback | 是 | 事件監(jiān)聽回調(diào)函數(shù),當(dāng)收到訂閱的事件時,回調(diào)訂閱的事件數(shù)據(jù) |
2.1.5、取消訂閱事件
function unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback<void>): void;
以異步方法取消訂閱公共事件,使用callback形式返回。與subscribe接口相同,需要傳入一個已創(chuàng)建的CommonEventSubscriber對象。
其中,參數(shù)定義如下:
參數(shù)名 | 類型 | 必填 | 說明 |
---|---|---|---|
subscribeInfo | CommonEventSubscribeInfo | 是 | 公共事件訂閱者信息 |
callback | AsyncCallback | 否 | 事件監(jiān)聽回調(diào)函數(shù),當(dāng)收到訂閱的事件時,回調(diào)訂閱的事件數(shù)據(jù) |
2.1.6、發(fā)布事件
function publish(event: string, callback: AsyncCallback<void>): void;
function publish(event: string, options: CommonEventPublishData, callback: AsyncCallback<void>): void;
function publishAsUser(event: string, userId: number, callback: AsyncCallback<void>): void;
function publishAsUser(event: string, userId: number, options: CommonEventPublishData, callback: AsyncCallback<void>): void;
以callback形式發(fā)布公共事件。
其中,參數(shù)定義如下:
參數(shù)名 | 類型 | 必填 | 說明 |
---|---|---|---|
subscribeInfo | CommonEventSubscribeInfo | 是 | 公共事件訂閱者信息 |
callback | AsyncCallback | 是 | 事件監(jiān)聽回調(diào)函數(shù),當(dāng)收到訂閱的事件時,回調(diào)訂閱的事件數(shù)據(jù) |
3、程序解析
按照頁面劃分,本案例大致可分為如下幾個頁面:
(1)Launch.ets:應(yīng)用顯示菜單頁面。進(jìn)入應(yīng)用顯示菜單頁,可選擇“進(jìn)入”,“歷史”,“設(shè)置”及“關(guān)于”幾個選項。
(2)Main.ets:主頁面。顯示“進(jìn)入監(jiān)控”按鍵,“開始監(jiān)控”按鈕,將開始監(jiān)聽系統(tǒng)公共事件,并進(jìn)行計時,此時按鈕內(nèi)容變更為“停止監(jiān)聽”;點擊停止監(jiān)聽按鈕,頁面上將顯示本次監(jiān)聽時長及監(jiān)聽期間收到的干擾信息匯總,并在頁面右下角顯示“查看詳情”按鈕,點擊按鈕將跳轉(zhuǎn)至詳情頁,顯示監(jiān)聽期間收到的干擾信息,應(yīng)用當(dāng)前僅監(jiān)聽了亮滅屏、斷聯(lián)網(wǎng)等用戶可操作的系統(tǒng)公共事件,后續(xù)可根據(jù)需求快速擴展。
(3)History.ets:歷史頁面。可查看用戶操作監(jiān)聽的歷史記錄,當(dāng)前支持每次運行期間最多存儲20條歷史記錄,超過20條后將刪除歷史數(shù)據(jù)。
(4)Setting.ets:設(shè)置頁面。可進(jìn)行具體系統(tǒng)事件的監(jiān)聽配置,應(yīng)用提供了“一直”、“僅本次”及“從不”三個選項,其中“僅本次”選項是指本次應(yīng)用運行期間將監(jiān)聽特定系統(tǒng)公共事件,應(yīng)用退出后該選項將自動調(diào)整為“從不”。
(5)Detail.ets:查看詳情頁面。可負(fù)責(zé)查看當(dāng)前監(jiān)控的具體信息。供Main.ets調(diào)用。
(6)About.ets:關(guān)于頁面。顯示軟件信息。
3.1、Launch.ets
首先,定義一個私有變量feature,用于負(fù)責(zé)具體的公共事件訂閱以及頁面間跳轉(zhuǎn)。
private feature :launchFeature = new launchFeature(getContext() as context.UIAbilityContext)
注意:feature具體事務(wù)可參考entry/src/main/ets/feature/LaunchFeature.ts。
其次,編輯頁面顯示界面。
build() {
Column() {
Image($rawfile('jumpToStart.png'))
.objectFit(ImageFit.Contain)
.width(160)
.height(75)
.onClick(this.feature.jumpToStart)
.position({ x: '30%', y: '20%' })
Image($rawfile('jumpToHistory.png'))
.objectFit(ImageFit.Contain)
.width(160)
.height(75)
.onClick(this.feature.jumpToHistory)
.position({ x: '30%', y: '35%' })
Image($rawfile('jumpTosetting.png'))
.objectFit(ImageFit.Contain)
.width(160)
.height(75)
.onClick(this.feature.jumpToSetting)
.position({ x: '30%', y: '50%' })
Image($rawfile('jumpAbout.png'))
.objectFit(ImageFit.Contain)
.width(160)
.height(75)
.onClick(this.feature.jumpToAbout)
.position({ x: '30%', y: '65%' })
}
.backgroundImage($rawfile('vbg720.png'))
.backgroundImageSize(ImageSize.Contain)
.width('100%')
.height('100%')
}
再次,創(chuàng)建LauchFeatrue.ts,主要負(fù)責(zé)頁面跳轉(zhuǎn)和記錄公共事件記錄。
其中,負(fù)責(zé)頁面跳轉(zhuǎn)的代碼如下所示:
jumpToHistory = () => {
Logger.info("ready to jump to history page")
router.push({
url: 'pages/History',
params: {}
})
}
jumpToSetting = () => {
Logger.info("ready to jump to setting page")
router.push({
url: 'pages/Setting',
params: {}
})
}
......
其中,記錄公共事件記錄的代碼如下所示:
private callbackFunc = (error, event) => {
this.pref.has(consts.DATA_BASE_KEY_TOTAL_TIMES, (err, ret) => {
if (ret) {
this.pref.get(consts.DATA_BASE_KEY_TOTAL_TIMES, []).then((value) => {
this.insertRecord(event, value)
})
} else {
let value: Array<string> = []
this.insertRecord(event, value)
}
})
if (this.currentRecordTimes >= consts.MAX_RECORD_NUM) {
this.subscriber.finishCommonEvent()
return
}
this.subscriber.abortCommonEvent()
this.subscriber.finishCommonEvent()
this.currentRecordTimes++
}
private callbackLowFunc = (error, event) => {
this.currentRecordTimes = 0
this.pref.get(consts.DATA_BASE_KEY_TOTAL_TIMES, []).then((value: Array<string>) => {
for (let i = 0; i < consts.MAX_RECORD_NUM; i++) {
this.pref.delete(value[i]).then(() => {
this.pref.flush()
})
}
})
this.currentRecordTimes = 0;
}
最后,定義onPageShow(),在用戶瀏覽頁面時觸發(fā)該事件。
async onPageShow() {
await this.feature.init()
}
3.2、Main.ets
首先,定義一個實際負(fù)責(zé)main頁面邏輯操作的類對象。
private feature:mainFeature = new mainFeature()
其次,在build()中定義按鍵畫面。
Image(this.btnSrc)
.objectFit(ImageFit.Contain).size({ width: 320, height: 150 })
.onClick(this.executeCallBack)
再次,this.executeCallBack()根據(jù)btnState數(shù)值變化開啟或關(guān)閉公共事件監(jiān)聽。
private executeCallBack = () => {
if (!this.btnState) {
this.handleStart()
} else {
this.handleStop()
}
}
再次,定義handleStart()開啟公共事件監(jiān)聽。
private handleStart = () => {
this.btnState = true
this.btnSrc = $rawfile('stop.png')
this.detailState = Visibility.None
this.currentState = Visibility.Visible
this.totalEventsInString = ''
this.totalEvents = 0
this.totalTimeInString = ''
// 獲取系統(tǒng)時間
sysTime.getCurrentTime().then((curTime) => {
this.startTime = curTime
let subscriberInfo = {
events: this.feature.getCurrentValidEvents()
}
// 創(chuàng)建訂閱者
commonEvent.createSubscriber(subscriberInfo, (error, subscriber) => {
this.validEventsSubscriber = subscriber
// 開啟訂閱事件
commonEvent.subscribe(subscriber, this.systemEventCallback)
})
})
}
最后,定義handleStop()關(guān)閉公共事件監(jiān)聽。
private handleStop = () => {
this.btnState = false
this.btnSrc = $rawfile('start.png')
this.detailState = Visibility.Visible
this.currentState = Visibility.None
this.totalEventsInString = this.totalEvents.toString()
// 刷新時間
sysTime.getCurrentTime().then((curTime) => {
this.totalTimeInString = utils.convertTimeToFormatString(curTime - this.startTime)
// 取消訂閱事件
commonEvent.unsubscribe(this.validEventsSubscriber, () => {
Logger.info("unsubscribe called")
})
let options = {
isOrdered: true,
parameters: {
'startTime': utils.getLocaleTime(this.startTime),
'endTime': utils.getLocaleTime(curTime),
'totalTime': this.totalTimeInString,
'totalEvents': this.totalEventsInString,
}
}
// 發(fā)布公共事件
commonEvent.publish(consts.COMMON_EVENT_FINISH_MEDITATION, options, () => {
Logger.info("success to publish COMMON_EVENT_FINISH_MEDITATION")
})
})
}
4、項目編譯
4.1、打開項目
打開DevEco Studio,再打開自定義通知項目。
4.2、編譯程序
點擊菜單欄上的“Build” -> "Rebuild Project"。如果出現(xiàn)無法編譯,則注意查看Event Log界面。如下所示:
點擊Run 'npm install',讓DevEco Studio安裝相關(guān)依賴包。
重新點擊菜單欄上的“Build” -> "Rebuild Project"。出現(xiàn)如下錯誤:
點擊上圖紅色框部分,安裝相關(guān)服務(wù)。
重新點擊菜單欄上的“Build” -> "Rebuild Project",編譯成功。
4.3、安裝程序
點擊“entry”按鈕,將項目程序安裝到設(shè)備端。如下圖所示:
如果出現(xiàn)下述報錯,表示無法安裝。如圖所示:
點擊上圖紅色框的藍(lán)色字體,彈出"Project Structure"對話框,點擊"Apply",再點擊"OK"。如圖所示:
重新點擊“entry”按鈕,將項目程序安裝到設(shè)備端。
5、運行結(jié)果
運行結(jié)果如下所示
-
APP
+關(guān)注
關(guān)注
33文章
1573瀏覽量
72482 -
應(yīng)用開發(fā)
+關(guān)注
關(guān)注
0文章
58瀏覽量
9361 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3722瀏覽量
16313
發(fā)布評論請先 登錄
相關(guān)推薦
評論