1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import installer from '@ohos.bundle.installer'; 17import launcherBundleManager from '@ohos.bundle.launcherBundleManager'; 18import bundleMonitor from '@ohos.bundle.bundleMonitor'; 19import osAccount from '@ohos.account.osAccount' 20import { AppItemInfo } from '../bean/AppItemInfo' 21import { CheckEmptyUtils } from '../utils/CheckEmptyUtils' 22import { CommonConstants } from '../constants/CommonConstants' 23import { EventConstants } from '../constants/EventConstants' 24import { ResourceManager } from './ResourceManager' 25import { Logger } from '../utils/Logger' 26import type { BusinessError } from '@ohos.base'; 27 28const TAG: string = 'LauncherAbilityManager' 29 30/** 31 * Wrapper class for innerBundleManager and formManager interfaces. 32 */ 33export class LauncherAbilityManager { 34 private static readonly BUNDLE_STATUS_CHANGE_KEY_REMOVE = 'remove' 35 private static readonly BUNDLE_STATUS_CHANGE_KEY_ADD = 'add' 36 private static launcherAbilityManager: LauncherAbilityManager = undefined 37 private readonly mAppMap = new Map<string, AppItemInfo>() 38 private mResourceManager: ResourceManager = undefined 39 private readonly mLauncherAbilityChangeListeners: any[] = [] 40 private mUserId: number = 100 41 private context: any = undefined 42 43 constructor(context) { 44 this.context = context 45 this.mResourceManager = ResourceManager.getInstance(context) 46 const osAccountManager = osAccount.getAccountManager() 47 osAccountManager.getOsAccountLocalIdFromProcess((err, localId) => { 48 Logger.debug(TAG, `getOsAccountLocalIdFromProcess localId ${localId}`) 49 this.mUserId = localId 50 }) 51 } 52 53 /** 54 * Get the application data model object. 55 * 56 * @return {object} application data model singleton 57 */ 58 static getInstance(context): LauncherAbilityManager { 59 if (this.launcherAbilityManager === null || this.launcherAbilityManager === undefined) { 60 this.launcherAbilityManager = new LauncherAbilityManager(context) 61 } 62 return this.launcherAbilityManager 63 } 64 65 /** 66 * get all app List info from BMS 67 * 68 * @return 应用的入口Ability信息列表 69 */ 70 async getLauncherAbilityList(): Promise<AppItemInfo[]> { 71 Logger.info(TAG, 'getLauncherAbilityList begin') 72 let abilityList = await launcherBundleManager.getAllLauncherAbilityInfo(this.mUserId) 73 const appItemInfoList = new Array<AppItemInfo>() 74 if (CheckEmptyUtils.isEmpty(abilityList)) { 75 Logger.info(TAG, 'getLauncherAbilityList Empty') 76 return appItemInfoList 77 } 78 for (let i = 0; i < abilityList.length; i++) { 79 let appItem = await this.transToAppItemInfo(abilityList[i]) 80 appItemInfoList.push(appItem) 81 } 82 return appItemInfoList 83 } 84 85 /** 86 * get AppItemInfo from BMS with bundleName 87 * @params bundleName 88 * @return AppItemInfo 89 */ 90 async getAppInfoByBundleName(bundleName: string): Promise<AppItemInfo | undefined> { 91 let appItemInfo: AppItemInfo | undefined = undefined 92 // get from cache 93 if (this.mAppMap != null && this.mAppMap.has(bundleName)) { 94 appItemInfo = this.mAppMap.get(bundleName) 95 } 96 if (appItemInfo != undefined) { 97 Logger.info(TAG, `getAppInfoByBundleName from cache: ${JSON.stringify(appItemInfo)}`) 98 return appItemInfo 99 } 100 // get from system 101 let abilityInfos = await launcherBundleManager.getLauncherAbilityInfo(bundleName, this.mUserId) 102 if (abilityInfos == undefined || abilityInfos.length == 0) { 103 Logger.info(TAG, `${bundleName} has no launcher ability`) 104 return undefined 105 } 106 let appInfo = abilityInfos[0] 107 const data = await this.transToAppItemInfo(appInfo) 108 Logger.info(TAG, `getAppInfoByBundleName from BMS: ${JSON.stringify(data)}`) 109 return data 110 } 111 112 private async transToAppItemInfo(info): Promise<AppItemInfo> { 113 const appItemInfo = new AppItemInfo() 114 appItemInfo.appName = await this.mResourceManager.getAppNameSync( 115 info.labelId, info.elementName.bundleName, info.applicationInfo.label 116 ) 117 appItemInfo.isSystemApp = info.applicationInfo.systemApp 118 appItemInfo.isUninstallAble = info.applicationInfo.removable 119 appItemInfo.appIconId = info.iconId 120 appItemInfo.appLabelId = info.labelId 121 appItemInfo.bundleName = info.elementName.bundleName 122 appItemInfo.abilityName = info.elementName.abilityName 123 await this.mResourceManager.updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName) 124 this.mAppMap.set(appItemInfo.bundleName, appItemInfo) 125 return appItemInfo 126 } 127 128 129 /** 130 * 启动应用 131 * 132 * @params paramAbilityName Ability名 133 * @params paramBundleName 应用包名 134 */ 135 startLauncherAbility(paramAbilityName, paramBundleName) { 136 Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`) 137 this.context.startAbility({ 138 bundleName: paramBundleName, 139 abilityName: paramAbilityName 140 }).then(() => { 141 Logger.info(TAG, 'startApplication promise success') 142 }, (err) => { 143 Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`) 144 }) 145 } 146 147 /** 148 * 通过桌面图标启动应用 149 * 150 * @params paramAbilityName Ability名 151 * @params paramBundleName 应用包名 152 */ 153 startLauncherAbilityFromRecent(paramAbilityName, paramBundleName): void { 154 Logger.info(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}`); 155 this.context.startRecentAbility({ 156 bundleName: paramBundleName, 157 abilityName: paramAbilityName 158 }).then(() => { 159 Logger.info(TAG, 'startApplication promise success'); 160 }, (err) => { 161 Logger.error(TAG, `startApplication promise error: ${JSON.stringify(err)}`); 162 }); 163 } 164 165 /** 166 * 卸载应用 167 * 168 * @params bundleName 应用包名 169 * @params callback 卸载回调 170 */ 171 async uninstallLauncherAbility(bundleName: string, callback): Promise<void> { 172 Logger.info(TAG, `uninstallLauncherAbility bundleName: ${bundleName}`); 173 const bundlerInstaller = await installer.getBundleInstaller(); 174 bundlerInstaller.uninstall(bundleName, { 175 userId: this.mUserId, 176 installFlag: 0, 177 isKeepData: false 178 }, (err: BusinessError) => { 179 Logger.info(TAG, `uninstallLauncherAbility result => ${JSON.stringify(err)}`); 180 callback(err); 181 }) 182 } 183 184 /** 185 * 开始监听系统应用状态. 186 * 187 * @params listener 监听对象 188 */ 189 registerLauncherAbilityChangeListener(listener: any): void { 190 if (!CheckEmptyUtils.isEmpty(listener)) { 191 if (this.mLauncherAbilityChangeListeners.length == 0) { 192 bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD, (bundleChangeInfo) => { 193 Logger.debug(TAG, `mBundleStatusCallback add bundleName: ${bundleChangeInfo.bundleName}, 194 userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`) 195 if (this.mUserId === bundleChangeInfo.userId) { 196 this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_ADDED, 197 bundleChangeInfo.bundleName, bundleChangeInfo.userId) 198 } 199 }) 200 bundleMonitor.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE, (bundleChangeInfo) => { 201 Logger.debug(TAG, `mBundleStatusCallback remove bundleName: ${bundleChangeInfo.bundleName}, 202 userId: ${bundleChangeInfo.userId}, mUserId ${this.mUserId}`) 203 if (this.mUserId === bundleChangeInfo.userId) { 204 this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_REMOVED, 205 bundleChangeInfo.bundleName, bundleChangeInfo.userId) 206 } 207 AppStorage.Set('isRefresh', true) 208 }) 209 } 210 const index = this.mLauncherAbilityChangeListeners.indexOf(listener) 211 if (index == CommonConstants.INVALID_VALUE) { 212 this.mLauncherAbilityChangeListeners.push(listener) 213 } 214 } 215 } 216 217 /** 218 * 取消监听系统应用状态. 219 * 220 * @params listener 监听对象 221 */ 222 unregisterLauncherAbilityChangeListener(listener: any): void { 223 if (!CheckEmptyUtils.isEmpty(listener)) { 224 const index = this.mLauncherAbilityChangeListeners.indexOf(listener) 225 if (index != CommonConstants.INVALID_VALUE) { 226 this.mLauncherAbilityChangeListeners.splice(index, 1) 227 } 228 if (this.mLauncherAbilityChangeListeners.length == 0) { 229 bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_ADD) 230 bundleMonitor.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY_REMOVE) 231 } 232 } 233 } 234 235 private notifyLauncherAbilityChange(event: string, bundleName: string, userId: number): void { 236 for (let index = 0; index < this.mLauncherAbilityChangeListeners.length; index++) { 237 this.mLauncherAbilityChangeListeners[index](event, bundleName, userId) 238 } 239 } 240}