0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

OpenHarmony開發(fā)實(shí)例:【仿桌面應(yīng)用】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-15 16:17 ? 次閱讀

介紹

本示例實(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ù)覽

image.png

使用說明

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è)面
鴻蒙HarmonyOSOpenHarmony知識(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]

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2376

    瀏覽量

    42922
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3730

    瀏覽量

    16424
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    OpenHarmony應(yīng)用開發(fā)安裝數(shù)學(xué)庫(kù)

    OpenHarmony應(yīng)用開發(fā)安裝數(shù)學(xué)庫(kù)
    的頭像 發(fā)表于 12-01 14:15 ?1196次閱讀
    <b class='flag-5'>OpenHarmony</b>應(yīng)用<b class='flag-5'>開發(fā)</b>安裝數(shù)學(xué)庫(kù)

    OpenHarmony南向開發(fā)實(shí)例:【游戲手柄】

    基于TS擴(kuò)展的聲明式開發(fā)范式編程語(yǔ)言,以及OpenHarmony的分布式能力實(shí)現(xiàn)的一個(gè)手柄游戲。
    的頭像 發(fā)表于 04-17 10:21 ?778次閱讀
    <b class='flag-5'>OpenHarmony</b>南向<b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)例</b>:【游戲手柄】

    OpenHarmony開發(fā)實(shí)例:【 待辦事項(xiàng)TodoList】

    TodoList應(yīng)用是基于OpenHarmony SDK開發(fā)的安裝在潤(rùn)和HiSpark Taurus AI Camera(Hi3516d)開發(fā)板標(biāo)準(zhǔn)系統(tǒng)上的應(yīng)用;應(yīng)用主要功能是以列表的形式,展示需要完成的日程;通過本demo可以
    的頭像 發(fā)表于 04-22 22:00 ?759次閱讀
    <b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)例</b>:【 待辦事項(xiàng)TodoList】

    HarmonyOS與OpenHarmony應(yīng)用開發(fā)差異

    DevEco Studio是HarmonyOS的配套的開發(fā)IDE,因?yàn)镠armonyOS是基于OpenHarmony開發(fā)的,因此,使用DevEco Studio(配套HarmonyOS)也可以進(jìn)行
    發(fā)表于 10-22 10:35

    OpenHarmony 應(yīng)用開發(fā)快速入門

    本文檔適用于OpenHarmony應(yīng)用開發(fā)的初學(xué)者。通過構(gòu)建一個(gè)簡(jiǎn)單的具有頁(yè)面跳轉(zhuǎn)/返回功能的應(yīng)用(如下圖所示),快速了解工程目錄的主要文件,熟悉OpenHarmony應(yīng)用開發(fā)流程。
    發(fā)表于 05-06 16:03

    openharmony開發(fā)企業(yè)有哪些

    將會(huì)在各種智能終端上運(yùn)用。那么openharmony開發(fā)企業(yè)有哪些?下面小編就為大家?guī)?b class='flag-5'>openharmony開發(fā)企業(yè)有哪些的答案。 openhar
    的頭像 發(fā)表于 06-23 11:13 ?2224次閱讀

    openharmony開發(fā)openharmony開發(fā)

    現(xiàn)在市面上支持OpenHarmony開發(fā)板已經(jīng)非常多了,OpenHarmony不僅僅只能在海思系列芯片上運(yùn)行,比較常見的有HiSpark、小熊派系列。這些開發(fā)板都是基于海思的Hi38
    的頭像 發(fā)表于 06-24 09:03 ?3708次閱讀

    使用Python開發(fā)OpenHarmony設(shè)備程序-I2C應(yīng)用實(shí)例分享

    在上一篇帖子《使用Python開發(fā)OpenHarmony設(shè)備程序(1-GPIO外設(shè)控制)》中,已經(jīng)成功的使用 Python 對(duì) GPIO 上的外設(shè)進(jìn)行了控制。這是非常重要的一個(gè)里程碑:在
    的頭像 發(fā)表于 12-07 11:34 ?3639次閱讀
    使用Python<b class='flag-5'>開發(fā)</b><b class='flag-5'>OpenHarmony</b>設(shè)備程序-I2C應(yīng)用<b class='flag-5'>實(shí)例</b>分享

    基于openharmony適配移植的仿通訊錄UI顯示控件

    項(xiàng)目介紹 項(xiàng)目名稱:RoundedLetterView 所屬系列:openharmony的第三方組件適配移植 功能:RoundedLetterView是一個(gè)仿通訊錄UI顯示的控件 項(xiàng)目移植狀態(tài):主
    發(fā)表于 03-30 09:39 ?2次下載

    OpenHarmony開發(fā)體系內(nèi)容介紹

    初學(xué)OpenHarmony開發(fā)者最需要構(gòu)建對(duì)OpenHarmony開發(fā)體系的整體了解。
    的頭像 發(fā)表于 07-04 10:34 ?1502次閱讀

    證通電子KS8123桌面智能終端設(shè)備通過OpenHarmony兼容性測(cè)評(píng)

    的一款搭載OpenAtom OpenHarmony(以下簡(jiǎn)稱“OpenHarmony”)3.1 Release系統(tǒng)的桌面智能終端設(shè)備(KS8123),通過了OpenHarmony 3.
    的頭像 發(fā)表于 12-01 21:05 ?926次閱讀

    openharmony開發(fā)應(yīng)用

    隨著智能設(shè)備的普及和多樣化,開發(fā)者們對(duì)于更加靈活、高效的操作系統(tǒng)需求與日俱增。在這個(gè)背景下,華為推出了OpenHarmony,一個(gè)全場(chǎng)景智能終端操作系統(tǒng)和生態(tài)平臺(tái)。本文將詳細(xì)探討
    的頭像 發(fā)表于 12-19 09:42 ?727次閱讀

    鴻蒙開發(fā)實(shí)例:【配置OpenHarmony SDK】

    在設(shè)置OpenHarmony應(yīng)用開發(fā)環(huán)境時(shí),需要開發(fā)者在DevEco Studio中配置對(duì)應(yīng)的SDK信息。
    的頭像 發(fā)表于 04-22 15:24 ?2069次閱讀
    鴻蒙<b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)例</b>:【配置<b class='flag-5'>OpenHarmony</b> SDK】

    OpenHarmony開發(fā)實(shí)例:【配置應(yīng)用簽名信息】

    使用真機(jī)設(shè)備運(yùn)行和調(diào)試OpenHarmony應(yīng)用前,需要對(duì)應(yīng)用進(jìn)行簽名才能正常運(yùn)行。
    的頭像 發(fā)表于 04-22 16:52 ?501次閱讀
    <b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)例</b>:【配置應(yīng)用簽名信息】

    基于ArkTS語(yǔ)言的OpenHarmony APP應(yīng)用開發(fā):HelloOpenharmony

    1、程序簡(jiǎn)介該程序是基于OpenHarmony標(biāo)準(zhǔn)系統(tǒng)編寫的UI應(yīng)用類:HelloOpenHarmony。本案例是基于API9接口開發(fā)。本案例已在OpenHarmony凌蒙派-RK35
    的頭像 發(fā)表于 09-15 08:09 ?432次閱讀
    基于ArkTS語(yǔ)言的<b class='flag-5'>OpenHarmony</b> APP應(yīng)用<b class='flag-5'>開發(fā)</b>:Hello<b class='flag-5'>Openharmony</b>