介绍
本示例实现了一个简单桌面应用,实现了以下几点功能:
1.展示了系统安装的应用,实现点击启动、应用上滑弹出卡片、卡片添加到桌面、卡片移除功能。
2.实现桌面数据持久化存储,应用支持卸载、监听应用卸载和安装并显示。
3.实现最近任务管理功能,包括任务卡片加锁、解锁、清理和清理所有任务功能。
4.通过点击应用图标或点击由长按图标弹出的菜单栏中的打开按钮的方式打开应用,是以打开最近任务方式拉起应用Ability。
效果预览
使用说明
1.安装编译的hap包,使用hdc shell aa start -b ohos.samples.launcher -a MainAbility命令启动应用,应用启动后显示系统安装的应用。
2.点击应用主界面上的应用图标可以启动应用,长按弹出菜单,点击打开可以正常启动应用。
3.图库等支持卡片的应用,长按菜单中有服务卡片,点击进入卡片预览界面,在卡片预览界面点击添加到桌面,返回到桌面并且卡片成功添加到桌面。
4.上滑图库等支持卡片的应用,可以弹出默认上滑卡片,点击上滑卡片右上角的+图标,可以添加卡片到桌面。
5.应用在桌面界面,使用hdc install安装一个应用,桌面可以监听到应用安装,并显示新安装的应用到桌面上。
6.应用在桌面界面,使用hdc uninstall 卸载第5步安装的应用,桌面可以监听到卸载,并移除桌面上的应用。
7.在桌面空白处上滑,可以进入最近任务管理界面,下滑任务卡片可以加锁/解锁,上滑卡片可以清理该后台任务,点击垃圾桶可以清除所有后台任务(加锁的应用不会被清理掉)。
代码解读
鸿蒙next开发文档参考了:qr23.cn/AKFP8k
点击或者复制转到。
entry/src/main/ets/
|---Application
| |---MyAbilityStage.ts
|---components
| |---FormManagerComponent.ets // 弹窗组件
|---MainAbility
| |---MainAbility.ts
|---manager
| |---WindowManager.ts // 数据类型
|---pages
| |---FormPage.ets // 首页
| |---Home.ets // 详情页面
| |---RecentsPage.ets // 详情页面
鸿蒙HarmonyOS与OpenHarmony知识更新+mau123789是v籽料领取
具体实现
获取应用功能模块
- 使用launcherBundleManager模块接口(系统能力:SystemCapability.BundleManager.BundleFramework),获取所有应用信息和给定包名获取应用信息,实现桌面展示所有安装的应用。使用on接口监听应用的安装和卸载从而实现应用安装和卸载刷新桌面。
源码链接:[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 应用的入口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 } /** * 启动应用 * * @params paramAbilityName Ability名 * @params paramBundleName 应用包名 */ 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)}`) }) } /** * 通过桌面图标启动应用 * * @params paramAbilityName Ability名 * @params paramBundleName 应用包名 */ 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)}`); }); } /** * 卸载应用 * * @params bundleName 应用包名 * @params callback 卸载回调 */ 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); }) } /** * 开始监听系统应用状态. * * @params listener 监听对象 */ 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) } } } /** * 取消监听系统应用状态. * * @params listener 监听对象 */ 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]
- 应用卸载功能模块
- 使用bundle模块的getBundleInstaller接口获取到BundleInstaller(系统能力:SystemCapability.BundleManager.BundleFramework),调用uninstall接口实现应用卸载功能。
源码链接:[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 应用的入口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 } /** * 启动应用 * * @params paramAbilityName Ability名 * @params paramBundleName 应用包名 */ 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)}`) }) } /** * 通过桌面图标启动应用 * * @params paramAbilityName Ability名 * @params paramBundleName 应用包名 */ 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)}`); }); } /** * 卸载应用 * * @params bundleName 应用包名 * @params callback 卸载回调 */ 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); }) } /** * 开始监听系统应用状态. * * @params listener 监听对象 */ 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) } } } /** * 取消监听系统应用状态. * * @params listener 监听对象 */ 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接口(系统能力:SystemCapability.Ability.Form),获取应用卡片信息,使用FormComponent组件展示卡片内容,从而实现添加卡片到桌面的功能。
- 源码链接:[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]
桌面数据持久化存储功能模块
- 使用关系型数据库rdb接口(系统能力:SystemCapability.DistributedDataManager.RelationalStore.Core),实现桌面数据持久化存储,存储应用的位置信息,卡片信息。
源码链接:[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]
加锁、解锁、清理后台任务功能模块
- 使用missionManager模块接口(系统能力:SystemCapability.Ability.AbilityRuntime.Mission),获取最近任务信息,并实现加锁、解锁、清理后台任务的功能。
- 源码链接:[MissionModel.ts]
- 接口参考:[@ohos.application.missionManager]
点击桌面应用拉起最近任务至前台功能模块
使用ServiceExtensionContext模块的startRecentAbility接口(系统能力:SystemCapability.Ability.AbilityRuntime.Core),拉起最近任务至前台显示,若应用Ability未启动时,则拉起新创建的应用Ability显示到前台。
源码链接:[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 应用的入口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 } /** * 启动应用 * * @params paramAbilityName Ability名 * @params paramBundleName 应用包名 */ 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)}`) }) } /** * 通过桌面图标启动应用 * * @params paramAbilityName Ability名 * @params paramBundleName 应用包名 */ 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)}`); }); } /** * 卸载应用 * * @params bundleName 应用包名 * @params callback 卸载回调 */ 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); }) } /** * 开始监听系统应用状态. * * @params listener 监听对象 */ 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) } } } /** * 取消监听系统应用状态. * * @params listener 监听对象 */ 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]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。