介紹
本示例實(shí)現(xiàn)了一個(gè)簡(jiǎn)單桌面應(yīng)用,實(shí)現(xiàn)了以下幾點(diǎn)功能:
1.展示了系統(tǒng)安裝的應(yīng)用,實(shí)現(xiàn)點(diǎn)擊啟動(dòng)、應(yīng)用上滑彈出卡片、卡片添加到桌面、卡片移除功能。
2.實(shí)現(xiàn)桌面數(shù)據(jù)持久化存儲(chǔ),應(yīng)用支持卸載、監(jiān)聽?wèi)?yīng)用卸載和安裝并顯示。
3.實(shí)現(xiàn)最近任務(wù)管理功能,包括任務(wù)卡片加鎖、解鎖、清理和清理所有任務(wù)功能。
4.通過點(diǎn)擊應(yīng)用圖標(biāo)或點(diǎn)擊由長(zhǎng)按圖標(biāo)彈出的菜單欄中的打開按鈕的方式打開應(yīng)用,是以打開最近任務(wù)方式拉起應(yīng)用Ability。
效果預(yù)覽
使用說明
1.安裝編譯的hap包,使用hdc shell aa start -b ohos.samples.launcher -a MainAbility命令啟動(dòng)應(yīng)用,應(yīng)用啟動(dòng)后顯示系統(tǒng)安裝的應(yīng)用。
2.點(diǎn)擊應(yīng)用主界面上的應(yīng)用圖標(biāo)可以啟動(dòng)應(yīng)用,長(zhǎng)按彈出菜單,點(diǎn)擊打開可以正常啟動(dòng)應(yīng)用。
3.圖庫(kù)等支持卡片的應(yīng)用,長(zhǎng)按菜單中有服務(wù)卡片,點(diǎn)擊進(jìn)入卡片預(yù)覽界面,在卡片預(yù)覽界面點(diǎn)擊 添加到桌面 ,返回到桌面并且卡片成功添加到桌面。
4.上滑圖庫(kù)等支持卡片的應(yīng)用,可以彈出默認(rèn)上滑卡片,點(diǎn)擊上滑卡片右上角的**+**圖標(biāo),可以添加卡片到桌面。
5.應(yīng)用在桌面界面,使用hdc install安裝一個(gè)應(yīng)用,桌面可以監(jiān)聽到應(yīng)用安裝,并顯示新安裝的應(yīng)用到桌面上。
6.應(yīng)用在桌面界面,使用hdc uninstall 卸載第5步安裝的應(yīng)用,桌面可以監(jiān)聽到卸載,并移除桌面上的應(yīng)用。
7.在桌面空白處上滑,可以進(jìn)入最近任務(wù)管理界面,下滑任務(wù)卡片可以加鎖/解鎖,上滑卡片可以清理該后臺(tái)任務(wù),點(diǎn)擊垃圾桶可以清除所有后臺(tái)任務(wù)(加鎖的應(yīng)用不會(huì)被清理掉)。
代碼解讀
entry/src/main/ets/
|---Application
| |---MyAbilityStage.ts
|---components
| |---FormManagerComponent.ets // 彈窗組件
|---MainAbility
| |---MainAbility.ts
|---manager
| |---WindowManager.ts // 數(shù)據(jù)類型
|---pages
| |---FormPage.ets // 首頁(yè)
| |---Home.ets // 詳情頁(yè)面
| |---RecentsPage.ets // 詳情頁(yè)面
鴻蒙HarmonyOS與OpenHarmony知識(shí)更新+mau123789是v籽料領(lǐng)取
###具體實(shí)現(xiàn)
![搜狗高速瀏覽器截圖20240326151344.png](//file1.elecfans.com/web2/M00/C6/C5/wKgaomYCyYKAZp6HAAB4LWPdpdQ014.jpg)
* 獲取應(yīng)用功能模塊
* 使用launcherBundleManager模塊接口(系統(tǒng)能力:SystemCapability.BundleManager.BundleFramework),獲取所有應(yīng)用信息和給定包名獲取應(yīng)用信息,實(shí)現(xiàn)桌面展示所有安裝的應(yīng)用。使用on接口監(jiān)聽?wèi)?yīng)用的安裝和卸載從而實(shí)現(xiàn)應(yīng)用安裝和卸載刷新桌面。
* 源碼鏈接:[LauncherAbilityManager.ts]
/*
Copyright (c) 2022-2023 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import installer from '@ohos.bundle.installer';
import launcherBundleManager from '@ohos.bundle.launcherBundleManager';
import bundleMonitor from '@ohos.bundle.bundleMonitor';
import osAccount from '@ohos.account.osAccount'
import { AppItemInfo } from '../bean/AppItemInfo'
import { CheckEmptyUtils } from '../utils/CheckEmptyUtils'
import { CommonConstants } from '../constants/CommonConstants'
import { EventConstants } from '../constants/EventConstants'
import { ResourceManager } from './ResourceManager'
import { Logger } from '../utils/Logger'
import type { BusinessError } from '@ohos.base';
const TAG: string = 'LauncherAbilityManager'
/**
- Wrapper class for innerBundleManager and formManager interfaces.
*/
export class LauncherAbilityManager {
private static readonly BUNDLE_STATUS_CHANGE_KEY_REMOVE = 'remove'
private static readonly BUNDLE_STATUS_CHANGE_KEY_ADD = 'add'
private static launcherAbilityManager: LauncherAbilityManager = undefined
private readonly mAppMap = new Map< string, AppItemInfo >()
private mResourceManager: ResourceManager = undefined
private readonly mLauncherAbilityChangeListeners: any[] = []
private mUserId: number = 100
private context: any = undefined
constructor(context) {
this.context = context
this.mResourceManager = ResourceManager.getInstance(context)
const osAccountManager = osAccount.getAccountManager()
osAccountManager.getOsAccountLocalIdFromProcess((err, localId) = > {
Logger.debug(TAG, `getOsAccountLocalIdFromProcess localId ${localId}`)
this.mUserId = localId
})
}
/**
Get the application data model object.
@return {object} application data model singleton
*/
static getInstance(context): LauncherAbilityManager {
if (this.launcherAbilityManager === null || this.launcherAbilityManager === undefined) {
this.launcherAbilityManager = new LauncherAbilityManager(context)
}
return this.launcherAbilityManager
}
/**
get all app List info from BMS
@return 應(yīng)用的入口Ability信息列表
*/
async getLauncherAbilityList(): Promise< AppItemInfo[] > {
Logger.info(TAG, 'getLauncherAbilityList begin')
let abilityList = await launcherBundleManager.getAllLauncherAbilityInfo(this.mUserId)
const appItemInfoList = new Array< AppItemInfo >()
if (CheckEmptyUtils.isEmpty(abilityList)) {
Logger.info(TAG, 'getLauncherAbilityList Empty')
return appItemInfoList
}
for (let i = 0; i < abilityList.length; i++) {
let appItem = await this.transToAppItemInfo(abilityList[i])
appItemInfoList.push(appItem)
}
return appItemInfoList
}
/**
get AppItemInfo from BMS with bundleName
@params bundleName
@return AppItemInfo
*/
async getAppInfoByBundleName(bundleName: string): Promise< AppItemInfo | undefined > {
let appItemInfo: AppItemInfo | undefined = undefined
// get from cache
if (this.mAppMap != null && this.mAppMap.has(bundleName)) {
appItemInfo = this.mAppMap.get(bundleName)
}
if (appItemInfo != undefined) {
Logger.info(TAG, `getAppInfoByBundleName from cache: ${JSON.stringify(appItemInfo)}`)
return appItemInfo
}
// get from system
let abilityInfos = await launcherBundleManager.getLauncherAbilityInfo(bundleName, this.mUserId)
if (abilityInfos == undefined || abilityInfos.length == 0) {
Logger.info(TAG, `${bundleName} has no launcher ability`)
return undefined
}
let appInfo = abilityInfos[0]
const data = await this.transToAppItemInfo(appInfo)
Logger.info(TAG, `getAppInfoByBundleName from BMS: ${JSON.stringify(data)}`)
return data
}
private async transToAppItemInfo(info): Promise< AppItemInfo > {
const appItemInfo = new AppItemInfo()
appItemInfo.appName = await this.mResourceManager.getAppNameSync(
info.labelId, info.elementName.bundleName, info.applicationInfo.label
)
appItemInfo.isSystemApp = info.applicationInfo.systemApp
appItemInfo.isUninstallAble = info.applicationInfo.removable
appItemInfo.appIconId = info.iconId
appItemInfo.appLabelId = info.labelId
appItemInfo.bundleName = info.elementName.bundleName
appItemInfo.abilityName = info.elementName.abilityName
await this.mResourceManager.updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName)
this.mAppMap.set(appItemInfo.bundleName, appItemInfo)
return appItemInfo
}
/**
啟動(dòng)應(yīng)用
@params paramAbilityName Ability名
@params paramBundleName 應(yīng)用包名
*/
startLauncherAbility(paramAbilityName, paramBundleName) {
Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`)
this.context.startAbility({
bundleName: paramBundleName,
abilityName: paramAbilityName
}).then(() = > {
Logger.info(TAG, 'startApplication promise success')
}, (err) = > {
Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`)
})
}
/**
通過桌面圖標(biāo)啟動(dòng)應(yīng)用
@params paramAbilityName Ability名
@params paramBundleName 應(yīng)用包名
*/
startLauncherAbilityFromRecent(paramAbilityName, paramBundleName): void {
Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`);
this.context.startRecentAbility({
bundleName: paramBundleName,
abilityName: paramAbilityName
}).then(() = > {
Logger.info(TAG, 'startApplication promise success');
}, (err) = > {
Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`);
});
}
/**
卸載應(yīng)用
@params bundleName 應(yīng)用包名
@params callback 卸載回調(diào)
*/
async uninstallLauncherAbility(bundleName: string, callback): Promise< void > {
Logger.info(TAG, `uninstallLauncherAbility bundleName: ${bundleName}`);
const bundlerInstaller = await installer.getBundleInstaller();
bundlerInstaller.uninstall(bundleName, {
userId: this.mUserId,
installFlag: 0,
isKeepData: false
}, (err: BusinessError) = > {
Logger.info(TAG, `uninstallLauncherAbility result = > ${JSON.stringify(err)}`);
callback(err);
})
}
/**
開始監(jiān)聽系統(tǒng)應(yīng)用狀態(tài).
@params listener 監(jiān)聽對(duì)象
*/
registerLauncherAbilityChangeListener(listener: any): void {
if (!CheckEmptyUtils.isEmpty(listener)) {
if (this.mLauncherAbilityChangeListeners.length == 0) {
bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD, (bundleChangeInfo) = > {
Logger.debug(TAG, `mBundleStatusCallback add bundleName: ${bundleChangeInfo.bundleName},
userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`)
if (this.mUserId === bundleChangeInfo.userId) {
this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_ADDED,
bundleChangeInfo.bundleName, bundleChangeInfo.userId)
}
})
bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE, (bundleChangeInfo) = > {
Logger.debug(TAG, `mBundleStatusCallback remove bundleName: ${bundleChangeInfo.bundleName},
userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`)
if (this.mUserId === bundleChangeInfo.userId) {
this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_REMOVED,
bundleChangeInfo.bundleName, bundleChangeInfo.userId)
}
AppStorage.Set('isRefresh', true)
})
}
const index = this.mLauncherAbilityChangeListeners.indexOf(listener)
if (index == CommonConstants.INVALID_VALUE) {
this.mLauncherAbilityChangeListeners.push(listener)
}
}
}
/**
取消監(jiān)聽系統(tǒng)應(yīng)用狀態(tài).
@params listener 監(jiān)聽對(duì)象
*/
unregisterLauncherAbilityChangeListener(listener: any): void {
if (!CheckEmptyUtils.isEmpty(listener)) {
const index = this.mLauncherAbilityChangeListeners.indexOf(listener)
if (index != CommonConstants.INVALID_VALUE) {
this.mLauncherAbilityChangeListeners.splice(index, 1)
}
if (this.mLauncherAbilityChangeListeners.length == 0) {
bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD)
bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE)
}
}
}
private notifyLauncherAbilityChange(event: string, bundleName: string, userId: number): void {
for (let index = 0; index < this.mLauncherAbilityChangeListeners.length; index++) {
this.mLauncherAbilityChangeListeners[index](event, bundleName, userId)
}
}
}
* 接口參考:[@ohos.bundle.launcherBundleManager]
* 應(yīng)用卸載功能模塊
* 使用bundle模塊的getBundleInstaller接口獲取到BundleInstaller(系統(tǒng)能力:SystemCapability.BundleManager.BundleFramework),調(diào)用uninstall接口實(shí)現(xiàn)應(yīng)用卸載功能。
* 源碼鏈接:[LauncherAbilityManager.ts]
/*
Copyright (c) 2022-2023 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import installer from '@ohos.bundle.installer';
import launcherBundleManager from '@ohos.bundle.launcherBundleManager';
import bundleMonitor from '@ohos.bundle.bundleMonitor';
import osAccount from '@ohos.account.osAccount'
import { AppItemInfo } from '../bean/AppItemInfo'
import { CheckEmptyUtils } from '../utils/CheckEmptyUtils'
import { CommonConstants } from '../constants/CommonConstants'
import { EventConstants } from '../constants/EventConstants'
import { ResourceManager } from './ResourceManager'
import { Logger } from '../utils/Logger'
import type { BusinessError } from '@ohos.base';
const TAG: string = 'LauncherAbilityManager'
/**
- Wrapper class for innerBundleManager and formManager interfaces.
*/
export class LauncherAbilityManager {
private static readonly BUNDLE_STATUS_CHANGE_KEY_REMOVE = 'remove'
private static readonly BUNDLE_STATUS_CHANGE_KEY_ADD = 'add'
private static launcherAbilityManager: LauncherAbilityManager = undefined
private readonly mAppMap = new Map< string, AppItemInfo >()
private mResourceManager: ResourceManager = undefined
private readonly mLauncherAbilityChangeListeners: any[] = []
private mUserId: number = 100
private context: any = undefined
constructor(context) {
this.context = context
this.mResourceManager = ResourceManager.getInstance(context)
const osAccountManager = osAccount.getAccountManager()
osAccountManager.getOsAccountLocalIdFromProcess((err, localId) = > {
Logger.debug(TAG, `getOsAccountLocalIdFromProcess localId ${localId}`)
this.mUserId = localId
})
}
/**
Get the application data model object.
@return {object} application data model singleton
*/
static getInstance(context): LauncherAbilityManager {
if (this.launcherAbilityManager === null || this.launcherAbilityManager === undefined) {
this.launcherAbilityManager = new LauncherAbilityManager(context)
}
return this.launcherAbilityManager
}
/**
get all app List info from BMS
@return 應(yīng)用的入口Ability信息列表
*/
async getLauncherAbilityList(): Promise< AppItemInfo[] > {
Logger.info(TAG, 'getLauncherAbilityList begin')
let abilityList = await launcherBundleManager.getAllLauncherAbilityInfo(this.mUserId)
const appItemInfoList = new Array< AppItemInfo >()
if (CheckEmptyUtils.isEmpty(abilityList)) {
Logger.info(TAG, 'getLauncherAbilityList Empty')
return appItemInfoList
}
for (let i = 0; i < abilityList.length; i++) {
let appItem = await this.transToAppItemInfo(abilityList[i])
appItemInfoList.push(appItem)
}
return appItemInfoList
}
/**
get AppItemInfo from BMS with bundleName
@params bundleName
@return AppItemInfo
*/
async getAppInfoByBundleName(bundleName: string): Promise< AppItemInfo | undefined > {
let appItemInfo: AppItemInfo | undefined = undefined
// get from cache
if (this.mAppMap != null && this.mAppMap.has(bundleName)) {
appItemInfo = this.mAppMap.get(bundleName)
}
if (appItemInfo != undefined) {
Logger.info(TAG, `getAppInfoByBundleName from cache: ${JSON.stringify(appItemInfo)}`)
return appItemInfo
}
// get from system
let abilityInfos = await launcherBundleManager.getLauncherAbilityInfo(bundleName, this.mUserId)
if (abilityInfos == undefined || abilityInfos.length == 0) {
Logger.info(TAG, `${bundleName} has no launcher ability`)
return undefined
}
let appInfo = abilityInfos[0]
const data = await this.transToAppItemInfo(appInfo)
Logger.info(TAG, `getAppInfoByBundleName from BMS: ${JSON.stringify(data)}`)
return data
}
private async transToAppItemInfo(info): Promise< AppItemInfo > {
const appItemInfo = new AppItemInfo()
appItemInfo.appName = await this.mResourceManager.getAppNameSync(
info.labelId, info.elementName.bundleName, info.applicationInfo.label
)
appItemInfo.isSystemApp = info.applicationInfo.systemApp
appItemInfo.isUninstallAble = info.applicationInfo.removable
appItemInfo.appIconId = info.iconId
appItemInfo.appLabelId = info.labelId
appItemInfo.bundleName = info.elementName.bundleName
appItemInfo.abilityName = info.elementName.abilityName
await this.mResourceManager.updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName)
this.mAppMap.set(appItemInfo.bundleName, appItemInfo)
return appItemInfo
}
/**
啟動(dòng)應(yīng)用
@params paramAbilityName Ability名
@params paramBundleName 應(yīng)用包名
*/
startLauncherAbility(paramAbilityName, paramBundleName) {
Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`)
this.context.startAbility({
bundleName: paramBundleName,
abilityName: paramAbilityName
}).then(() = > {
Logger.info(TAG, 'startApplication promise success')
}, (err) = > {
Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`)
})
}
/**
通過桌面圖標(biāo)啟動(dòng)應(yīng)用
@params paramAbilityName Ability名
@params paramBundleName 應(yīng)用包名
*/
startLauncherAbilityFromRecent(paramAbilityName, paramBundleName): void {
Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`);
this.context.startRecentAbility({
bundleName: paramBundleName,
abilityName: paramAbilityName
}).then(() = > {
Logger.info(TAG, 'startApplication promise success');
}, (err) = > {
Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`);
});
}
/**
卸載應(yīng)用
@params bundleName 應(yīng)用包名
@params callback 卸載回調(diào)
*/
async uninstallLauncherAbility(bundleName: string, callback): Promise< void > {
Logger.info(TAG, `uninstallLauncherAbility bundleName: ${bundleName}`);
const bundlerInstaller = await installer.getBundleInstaller();
bundlerInstaller.uninstall(bundleName, {
userId: this.mUserId,
installFlag: 0,
isKeepData: false
}, (err: BusinessError) = > {
Logger.info(TAG, `uninstallLauncherAbility result = > ${JSON.stringify(err)}`);
callback(err);
})
}
/**
開始監(jiān)聽系統(tǒng)應(yīng)用狀態(tài).
@params listener 監(jiān)聽對(duì)象
*/
registerLauncherAbilityChangeListener(listener: any): void {
if (!CheckEmptyUtils.isEmpty(listener)) {
if (this.mLauncherAbilityChangeListeners.length == 0) {
bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD, (bundleChangeInfo) = > {
Logger.debug(TAG, `mBundleStatusCallback add bundleName: ${bundleChangeInfo.bundleName},
userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`)
if (this.mUserId === bundleChangeInfo.userId) {
this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_ADDED,
bundleChangeInfo.bundleName, bundleChangeInfo.userId)
}
})
bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE, (bundleChangeInfo) = > {
Logger.debug(TAG, `mBundleStatusCallback remove bundleName: ${bundleChangeInfo.bundleName},
userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`)
if (this.mUserId === bundleChangeInfo.userId) {
this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_REMOVED,
bundleChangeInfo.bundleName, bundleChangeInfo.userId)
}
AppStorage.Set('isRefresh', true)
})
}
const index = this.mLauncherAbilityChangeListeners.indexOf(listener)
if (index == CommonConstants.INVALID_VALUE) {
this.mLauncherAbilityChangeListeners.push(listener)
}
}
}
/**
取消監(jiān)聽系統(tǒng)應(yīng)用狀態(tài).
@params listener 監(jiān)聽對(duì)象
*/
unregisterLauncherAbilityChangeListener(listener: any): void {
if (!CheckEmptyUtils.isEmpty(listener)) {
const index = this.mLauncherAbilityChangeListeners.indexOf(listener)
if (index != CommonConstants.INVALID_VALUE) {
this.mLauncherAbilityChangeListeners.splice(index, 1)
}
if (this.mLauncherAbilityChangeListeners.length == 0) {
bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD)
bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE)
}
}
}
private notifyLauncherAbilityChange(event: string, bundleName: string, userId: number): void {
for (let index = 0; index < this.mLauncherAbilityChangeListeners.length; index++) {
this.mLauncherAbilityChangeListeners[index](event, bundleName, userId)
}
}
}
* 接口參考:[@ohos.bundle]
* 添加卡片功能模塊
* 使用formHost接口(系統(tǒng)能力:SystemCapability.Ability.Form),獲取應(yīng)用卡片信息,使用FormComponent組件展示卡片內(nèi)容,從而實(shí)現(xiàn)添加卡片到桌面的功能。
* 源碼鏈接:[FormManager.ts]
/*
Copyright (c) 2022 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import formManagerAbility from '@ohos.app.form.formHost'
import { CardItemInfo } from '../bean/CardItemInfo'
import { CommonConstants } from '../constants/CommonConstants'
import { Logger } from '../utils/Logger'
const TAG: string = 'FormManager'
/**
- Wrapper class for formManager interfaces.
*/
class FormManagerModel {
private readonly CARD_SIZE_1x2: number[] = [1, 2]
private readonly CARD_SIZE_2x2: number[] = [2, 2]
private readonly CARD_SIZE_2x4: number[] = [2, 4]
private readonly CARD_SIZE_4x4: number[] = [4, 4]
/**
get all form info
@return Array< CardItemInfo > cardItemInfoList
*/
public async getAllFormsInfo(): Promise< CardItemInfo[] > {
const formList = await formManagerAbility.getAllFormsInfo()
const cardItemInfoList = new Array< CardItemInfo >()
for (const formItem of formList) {
const cardItemInfo = new CardItemInfo()
cardItemInfo.bundleName = formItem.bundleName
cardItemInfo.abilityName = formItem.abilityName
cardItemInfo.moduleName = formItem.moduleName
cardItemInfo.cardName = formItem.name
cardItemInfo.cardDimension = formItem.defaultDimension
cardItemInfo.description = formItem.description
cardItemInfo.formConfigAbility = formItem.formConfigAbility
cardItemInfo.supportDimensions = formItem.supportDimensions
cardItemInfo.area = this.getCardSize(cardItemInfo.cardDimension)
cardItemInfoList.push(cardItemInfo)
}
return cardItemInfoList
}
/**
get card area by dimension
@param dimension
@return number[]
*/
public getCardSize(dimension: number): number[] {
if (dimension == CommonConstants.CARD_DIMENSION_1x2) {
return this.CARD_SIZE_1x2
} else if (dimension == CommonConstants.CARD_DIMENSION_2x2) {
return this.CARD_SIZE_2x2
} else if (dimension == CommonConstants.CARD_DIMENSION_2x4) {
return this.CARD_SIZE_2x4
} else {
return this.CARD_SIZE_4x4
}
}
/**
get card dimension bty area
@param dimension
@return number[]
*/
public getCardDimension(area: number[]) {
if (area.toString() === this.CARD_SIZE_1x2.toString()) {
return CommonConstants.CARD_DIMENSION_1x2
} else if (area.toString() === this.CARD_SIZE_2x2.toString()) {
return CommonConstants.CARD_DIMENSION_2x2
} else if (area.toString() == this.CARD_SIZE_2x4.toString()) {
return CommonConstants.CARD_DIMENSION_2x4
} else {
return CommonConstants.CARD_DIMENSION_4x4
}
}
/**
get form info by bundleName
@param bundle
@return Array< CardItemInfo > cardItemInfoList
*/
public async getFormsInfoByApp(bundle: string): Promise< CardItemInfo[] > {
Logger.info(TAG, `getFormsInfoByApp bundle: ${bundle}`)
const formList = await formManagerAbility.getFormsInfo(bundle)
const cardItemInfoList = new Array< CardItemInfo >()
for (const formItem of formList) {
const cardItemInfo = new CardItemInfo()
cardItemInfo.bundleName = formItem.bundleName
cardItemInfo.abilityName = formItem.abilityName
cardItemInfo.moduleName = formItem.moduleName
cardItemInfo.cardName = formItem.name
cardItemInfo.cardDimension = formItem.defaultDimension
cardItemInfo.area = this.getCardSize(cardItemInfo.cardDimension)
cardItemInfo.description = formItem.description
cardItemInfo.formConfigAbility = formItem.formConfigAbility
cardItemInfo.supportDimensions = formItem.supportDimensions
cardItemInfoList.push(cardItemInfo)
}
return cardItemInfoList
}
}
export let FormManager = new FormManagerModel()
* 接口參考:[@ohos.app.form.formHost]
* 桌面數(shù)據(jù)持久化存儲(chǔ)功能模塊
* 使用關(guān)系型數(shù)據(jù)庫(kù)rdb接口(系統(tǒng)能力:SystemCapability.DistributedDataManager.RelationalStore.Core),實(shí)現(xiàn)桌面數(shù)據(jù)持久化存儲(chǔ),存儲(chǔ)應(yīng)用的位置信息,卡片信息。
* 源碼鏈接:[RdbManager.ts]
/*
Copyright (c) 2022-2023 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import dataRdb from '@ohos.data.relationalStore'
import { CheckEmptyUtils } from '../utils/CheckEmptyUtils'
import { CommonConstants } from '../constants/CommonConstants'
import { GridLayoutItemInfo } from '../bean/GridLayoutItemInfo'
import { GridLayoutInfoColumns } from '../bean/GridLayoutInfoColumns'
import { Logger } from '../utils/Logger'
export const TABLE_NAME: string = 'launcher'
export const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS launcher ' +
'(id INTEGER PRIMARY KEY AUTOINCREMENT, ' +
'app_name TEXT, ' +
'appIcon_id INTEGER, ' +
'container INTEGER, ' +
'type_id INTEGER, ' +
'card_id INTEGER, ' +
'card_name TEXT, ' +
'badge_number INTEGER, ' +
'module_name TEXT, ' +
'bundle_name TEXT, ' +
'ability_name TEXT, ' +
'area TEXT, ' +
'page INTEGER, ' +
'column INTEGER, ' +
'row INTEGER)'
export const STORE_CONFIG = { name: 'launcher.db', securityLevel: dataRdb.SecurityLevel.S1 }
const TAG: string = 'RdbModel'
class RdbManagerModel {
private mRdbStore: dataRdb.RdbStore = undefined
constructor() {
}
/**
initRdbConfig
@param context
*/
async initRdbConfig(context): Promise< void > {
Logger.info(TAG, 'initRdbConfig start')
if (this.mRdbStore === undefined) {
this.mRdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG);
await this.mRdbStore.executeSql(SQL_CREATE_TABLE);
Logger.info(TAG, 'create table end');
}
}
/**
deleteTable
@param tableName
*/
async deleteTable(tableName: string): Promise< void > {
Logger.info(TAG, 'deleteTable start')
try {
let detelSql = `DELETE FROM ${tableName};`
let detelSequenceSql = `UPDATE sqlite_sequence SET seq=0 WHERE name = '${tableName}';`
await this.mRdbStore.executeSql(detelSql)
await this.mRdbStore.executeSql(detelSequenceSql)
Logger.debug(TAG, 'deleteTable end')
} catch (e) {
Logger.error(TAG, `deleteTable err: ${e}`)
}
}
/**
insertData
@param layoutInfo
*/
async insertData(layoutInfo: any) {
Logger.info(TAG, 'insertGridLayoutInfo start');
let result: boolean = true
if (CheckEmptyUtils.isEmpty(layoutInfo)) {
Logger.error(TAG, 'insertGridLayoutInfo gridlayoutinfo is empty')
result = false
return result
}
try {
// delete gridlayoutinfo table
await this.deleteTable(TABLE_NAME)
// insert into gridlayoutinfo
for (let i in layoutInfo) {
let layout = layoutInfo[i]
for (let j in layout) {
let element = layout[j]
Logger.info(TAG, `insertGridLayoutInfo i= ${i}`)
let item = {}
if (element.typeId === CommonConstants.TYPE_APP) {
item = {
'app_name': element.appName,
'bundle_name': element.bundleName,
'module_name': element.modelName,
'ability_name': element.abilityName,
'appIcon_id': element.appIconId,
'type_id': element.typeId,
'area': element.area[0] + ',' + element.area[1],
'page': element.page,
'column': element.column,
'row': element.row,
'container': -100
}
let ret = await this.mRdbStore.insert(TABLE_NAME, item)
Logger.debug(TAG, `insertGridLayoutInfo type is app ${i} ret: ${ret}`)
} else if (element.typeId === CommonConstants.TYPE_CARD) {
item = {
'app_name': element.appName,
'bundle_name': element.bundleName,
'module_name': element.modelName,
'ability_name': element.abilityName,
'card_id': element.cardId,
'card_name': element.cardName,
'type_id': element.typeId,
'area': element.area[0] + ',' + element.area[1],
'page': element.page,
'column': element.column,
'row': element.row,
'container': -100
}
let ret = await this.mRdbStore.insert(TABLE_NAME, item)
Logger.debug(TAG, `insertGridLayoutInfo type is card ${i} ret: ${ret}`)
}
}
}
} catch (e) {
Logger.error(TAG, `insertGridLayoutInfo error: ${e}`)
}
return result
}
async queryLayoutInfo() {
Logger.info(TAG, 'queryLayoutInfo start')
const resultList: GridLayoutItemInfo[] = []
const predicates = new dataRdb.RdbPredicates(TABLE_NAME)
predicates.equalTo(GridLayoutInfoColumns.CONTAINER, -100)
.and().orderByAsc('page').and().orderByAsc('row').and().orderByAsc('column')
let resultSet = await this.mRdbStore.query(predicates)
Logger.info(TAG, `queryLayoutInfo query,count=${resultSet.rowCount}`)
let isLast = resultSet.goToFirstRow()
while (isLast) {
const layoutInfo: GridLayoutItemInfo = GridLayoutItemInfo.fromResultSet(resultSet)
resultList.push(layoutInfo)
isLast = resultSet.goToNextRow()
}
resultSet.close()
resultSet = null
return resultList
}
async insertItem(item: GridLayoutItemInfo) {
if (CheckEmptyUtils.isEmpty(item)) {
return
}
let element = {
'app_name': item.appName,
'module_name': item.moduleName,
'bundle_name': item.bundleName,
'ability_name': item.abilityName,
'appIcon_id': item.appIconId,
'card_id': item.cardId,
'card_name': item.cardName,
'type_id': item.typeId,
'area': item.area[0] + ',' + item.area[1],
'page': item.page,
'column': item.column,
'row': item.row,
'container': -100
}
let ret = await this.mRdbStore.insert(TABLE_NAME, element)
Logger.debug(TAG, `insertGridLayoutInfo ret: ${ret}`)
}
async deleteItemByPosition(page: number, row: number, column: number) {
const predicates = new dataRdb.RdbPredicates(TABLE_NAME);
predicates.equalTo('page', page)
.and().equalTo('row', row)
.and().equalTo('column', column);
let query = await this.mRdbStore.query(predicates);
if (query.rowCount > 0) {
let ret = await this.mRdbStore.delete(predicates);
Logger.debug(TAG, `deleteItem ret: ${ret}`);
}
}
}
export let RdbManager = new RdbManagerModel()
* 接口參考:[@ohos.data.relationalStore]
* 加鎖、解鎖、清理后臺(tái)任務(wù)功能模塊
* 使用missionManager模塊接口(系統(tǒng)能力:SystemCapability.Ability.AbilityRuntime.Mission),獲取最近任務(wù)信息,并實(shí)現(xiàn)加鎖、解鎖、清理后臺(tái)任務(wù)的功能。
* 源碼鏈接:[MissionModel.ts]
* 接口參考:[@ohos.application.missionManager]
* 點(diǎn)擊桌面應(yīng)用拉起最近任務(wù)至前臺(tái)功能模塊
* 使用ServiceExtensionContext模塊的startRecentAbility接口(系統(tǒng)能力:SystemCapability.Ability.AbilityRuntime.Core),拉起最近任務(wù)至前臺(tái)顯示,若應(yīng)用Ability未啟動(dòng)時(shí),則拉起新創(chuàng)建的應(yīng)用Ability顯示到前臺(tái)。
源碼鏈接:[LauncherAbilityManager.ts]
/*
Copyright (c) 2022-2023 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import installer from '@ohos.bundle.installer';
import launcherBundleManager from '@ohos.bundle.launcherBundleManager';
import bundleMonitor from '@ohos.bundle.bundleMonitor';
import osAccount from '@ohos.account.osAccount'
import { AppItemInfo } from '../bean/AppItemInfo'
import { CheckEmptyUtils } from '../utils/CheckEmptyUtils'
import { CommonConstants } from '../constants/CommonConstants'
import { EventConstants } from '../constants/EventConstants'
import { ResourceManager } from './ResourceManager'
import { Logger } from '../utils/Logger'
import type { BusinessError } from '@ohos.base';
const TAG: string = 'LauncherAbilityManager'
/**
- Wrapper class for innerBundleManager and formManager interfaces.
*/
export class LauncherAbilityManager {
private static readonly BUNDLE_STATUS_CHANGE_KEY_REMOVE = 'remove'
private static readonly BUNDLE_STATUS_CHANGE_KEY_ADD = 'add'
private static launcherAbilityManager: LauncherAbilityManager = undefined
private readonly mAppMap = new Map< string, AppItemInfo >()
private mResourceManager: ResourceManager = undefined
private readonly mLauncherAbilityChangeListeners: any[] = []
private mUserId: number = 100
private context: any = undefined
constructor(context) {
this.context = context
this.mResourceManager = ResourceManager.getInstance(context)
const osAccountManager = osAccount.getAccountManager()
osAccountManager.getOsAccountLocalIdFromProcess((err, localId) = > {
Logger.debug(TAG, `getOsAccountLocalIdFromProcess localId ${localId}`)
this.mUserId = localId
})
}
/**
Get the application data model object.
@return {object} application data model singleton
*/
static getInstance(context): LauncherAbilityManager {
if (this.launcherAbilityManager === null || this.launcherAbilityManager === undefined) {
this.launcherAbilityManager = new LauncherAbilityManager(context)
}
return this.launcherAbilityManager
}
/**
get all app List info from BMS
@return 應(yīng)用的入口Ability信息列表
*/
async getLauncherAbilityList(): Promise< AppItemInfo[] > {
Logger.info(TAG, 'getLauncherAbilityList begin')
let abilityList = await launcherBundleManager.getAllLauncherAbilityInfo(this.mUserId)
const appItemInfoList = new Array< AppItemInfo >()
if (CheckEmptyUtils.isEmpty(abilityList)) {
Logger.info(TAG, 'getLauncherAbilityList Empty')
return appItemInfoList
}
for (let i = 0; i < abilityList.length; i++) {
let appItem = await this.transToAppItemInfo(abilityList[i])
appItemInfoList.push(appItem)
}
return appItemInfoList
}
/**
get AppItemInfo from BMS with bundleName
@params bundleName
@return AppItemInfo
*/
async getAppInfoByBundleName(bundleName: string): Promise< AppItemInfo | undefined > {
let appItemInfo: AppItemInfo | undefined = undefined
// get from cache
if (this.mAppMap != null && this.mAppMap.has(bundleName)) {
appItemInfo = this.mAppMap.get(bundleName)
}
if (appItemInfo != undefined) {
Logger.info(TAG, `getAppInfoByBundleName from cache: ${JSON.stringify(appItemInfo)}`)
return appItemInfo
}
// get from system
let abilityInfos = await launcherBundleManager.getLauncherAbilityInfo(bundleName, this.mUserId)
if (abilityInfos == undefined || abilityInfos.length == 0) {
Logger.info(TAG, `${bundleName} has no launcher ability`)
return undefined
}
let appInfo = abilityInfos[0]
const data = await this.transToAppItemInfo(appInfo)
Logger.info(TAG, `getAppInfoByBundleName from BMS: ${JSON.stringify(data)}`)
return data
}
private async transToAppItemInfo(info): Promise< AppItemInfo > {
const appItemInfo = new AppItemInfo()
appItemInfo.appName = await this.mResourceManager.getAppNameSync(
info.labelId, info.elementName.bundleName, info.applicationInfo.label
)
appItemInfo.isSystemApp = info.applicationInfo.systemApp
appItemInfo.isUninstallAble = info.applicationInfo.removable
appItemInfo.appIconId = info.iconId
appItemInfo.appLabelId = info.labelId
appItemInfo.bundleName = info.elementName.bundleName
appItemInfo.abilityName = info.elementName.abilityName
await this.mResourceManager.updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName)
this.mAppMap.set(appItemInfo.bundleName, appItemInfo)
return appItemInfo
}
/**
啟動(dòng)應(yīng)用
@params paramAbilityName Ability名
@params paramBundleName 應(yīng)用包名
*/
startLauncherAbility(paramAbilityName, paramBundleName) {
Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`)
this.context.startAbility({
bundleName: paramBundleName,
abilityName: paramAbilityName
}).then(() = > {
Logger.info(TAG, 'startApplication promise success')
}, (err) = > {
Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`)
})
}
/**
通過桌面圖標(biāo)啟動(dòng)應(yīng)用
@params paramAbilityName Ability名
@params paramBundleName 應(yīng)用包名
*/
startLauncherAbilityFromRecent(paramAbilityName, paramBundleName): void {
Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`);
this.context.startRecentAbility({
bundleName: paramBundleName,
abilityName: paramAbilityName
}).then(() = > {
Logger.info(TAG, 'startApplication promise success');
}, (err) = > {
Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`);
});
}
/**
卸載應(yīng)用
@params bundleName 應(yīng)用包名
@params callback 卸載回調(diào)
*/
async uninstallLauncherAbility(bundleName: string, callback): Promise< void > {
Logger.info(TAG, `uninstallLauncherAbility bundleName: ${bundleName}`);
const bundlerInstaller = await installer.getBundleInstaller();
bundlerInstaller.uninstall(bundleName, {
userId: this.mUserId,
installFlag: 0,
isKeepData: false
}, (err: BusinessError) = > {
Logger.info(TAG, `uninstallLauncherAbility result = > ${JSON.stringify(err)}`);
callback(err);
})
}
/**
開始監(jiān)聽系統(tǒng)應(yīng)用狀態(tài).
@params listener 監(jiān)聽對(duì)象
*/
registerLauncherAbilityChangeListener(listener: any): void {
if (!CheckEmptyUtils.isEmpty(listener)) {
if (this.mLauncherAbilityChangeListeners.length == 0) {
bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD, (bundleChangeInfo) = > {
Logger.debug(TAG, `mBundleStatusCallback add bundleName: ${bundleChangeInfo.bundleName},
userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`)
if (this.mUserId === bundleChangeInfo.userId) {
this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_ADDED,
bundleChangeInfo.bundleName, bundleChangeInfo.userId)
}
})
bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE, (bundleChangeInfo) = > {
Logger.debug(TAG, `mBundleStatusCallback remove bundleName: ${bundleChangeInfo.bundleName},
userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`)
if (this.mUserId === bundleChangeInfo.userId) {
this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_REMOVED,
bundleChangeInfo.bundleName, bundleChangeInfo.userId)
}
AppStorage.Set('isRefresh', true)
})
}
const index = this.mLauncherAbilityChangeListeners.indexOf(listener)
if (index == CommonConstants.INVALID_VALUE) {
this.mLauncherAbilityChangeListeners.push(listener)
}
}
}
/**
取消監(jiān)聽系統(tǒng)應(yīng)用狀態(tài).
@params listener 監(jiān)聽對(duì)象
*/
unregisterLauncherAbilityChangeListener(listener: any): void {
if (!CheckEmptyUtils.isEmpty(listener)) {
const index = this.mLauncherAbilityChangeListeners.indexOf(listener)
if (index != CommonConstants.INVALID_VALUE) {
this.mLauncherAbilityChangeListeners.splice(index, 1)
}
if (this.mLauncherAbilityChangeListeners.length == 0) {
bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD)
bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE)
}
}
}
private notifyLauncherAbilityChange(event: string, bundleName: string, userId: number): void {
for (let index = 0; index < this.mLauncherAbilityChangeListeners.length; index++) {
this.mLauncherAbilityChangeListeners[index](event, bundleName, userId)
}
}
}
接口參考:[@ohos.app.ability.ServiceExtensionAbility]
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
57文章
2376瀏覽量
42922 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3730瀏覽量
16424
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論