• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}