<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

OpenHarmony開發實例:【仿桌面應用】

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

介紹

本示例實現了一個簡單桌面應用,實現了以下幾點功能:

1.展示了系統安裝的應用,實現點擊啟動、應用上滑彈出卡片、卡片添加到桌面、卡片移除功能。

2.實現桌面數據持久化存儲,應用支持卸載、監聽應用卸載和安裝并顯示。

3.實現最近任務管理功能,包括任務卡片加鎖、解鎖、清理和清理所有任務功能。

4.通過點擊應用圖標或點擊由長按圖標彈出的菜單欄中的打開按鈕的方式打開應用,是以打開最近任務方式拉起應用Ability。

效果預覽

image.png

使用說明

1.安裝編譯的hap包,使用hdc shell aa start -b ohos.samples.launcher -a MainAbility命令啟動應用,應用啟動后顯示系統安裝的應用。

2.點擊應用主界面上的應用圖標可以啟動應用,長按彈出菜單,點擊打開可以正常啟動應用。

3.圖庫等支持卡片的應用,長按菜單中有服務卡片,點擊進入卡片預覽界面,在卡片預覽界面點擊 添加到桌面 ,返回到桌面并且卡片成功添加到桌面。

4.上滑圖庫等支持卡片的應用,可以彈出默認上滑卡片,點擊上滑卡片右上角的**+**圖標,可以添加卡片到桌面。

5.應用在桌面界面,使用hdc install安裝一個應用,桌面可以監聽到應用安裝,并顯示新安裝的應用到桌面上。

6.應用在桌面界面,使用hdc uninstall 卸載第5步安裝的應用,桌面可以監聽到卸載,并移除桌面上的應用。

7.在桌面空白處上滑,可以進入最近任務管理界面,下滑任務卡片可以加鎖/解鎖,上滑卡片可以清理該后臺任務,點擊垃圾桶可以清除所有后臺任務(加鎖的應用不會被清理掉)。

代碼解讀

entry/src/main/ets/
|---Application
| |---MyAbilityStage.ts
|---components
| |---FormManagerComponent.ets // 彈窗組件
|---MainAbility
| |---MainAbility.ts
|---manager
| |---WindowManager.ts // 數據類型
|---pages
| |---FormPage.ets // 首頁
| |---Home.ets // 詳情頁面
| |---RecentsPage.ets // 詳情頁面
鴻蒙HarmonyOSOpenHarmony知識更新+mau123789是v籽料領取


###具體實現

![搜狗高速瀏覽器截圖20240326151344.png](//file1.elecfans.com/web2/M00/C6/C5/wKgaomYCyYKAZp6HAAB4LWPdpdQ014.jpg)

* 獲取應用功能模塊
  * 使用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]

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙
    +關注

    關注

    55

    文章

    1760

    瀏覽量

    42153
  • OpenHarmony
    +關注

    關注

    23

    文章

    3375

    瀏覽量

    15192
收藏 人收藏

    評論

    相關推薦

    玩嗨OpenHarmony:基于OpenHarmony的仿生四足狗開發分享

    原文引自51CTO 開源基礎軟件社區 《劉瀟翔:基于OpenHarmony的仿生四足狗開發分享》 作者介紹 劉瀟翔, 現就讀于南方科技大學(Southern University
    的頭像 發表于 10-31 21:50 ?3196次閱讀

    OpenHarmony應用開發安裝數學庫

    OpenHarmony應用開發安裝數學庫
    的頭像 發表于 12-01 14:15 ?960次閱讀
    <b class='flag-5'>OpenHarmony</b>應用<b class='flag-5'>開發</b>安裝數學庫

    OpenHarmony南向開發實例:【游戲手柄】

    基于TS擴展的聲明式開發范式編程語言,以及OpenHarmony的分布式能力實現的一個手柄游戲。
    的頭像 發表于 04-17 10:21 ?440次閱讀
    <b class='flag-5'>OpenHarmony</b>南向<b class='flag-5'>開發</b><b class='flag-5'>實例</b>:【游戲手柄】

    OpenHarmony開發實例:【 待辦事項TodoList】

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

    HarmonyOS與OpenHarmony應用開發差異

    DevEco Studio是HarmonyOS的配套的開發IDE,因為HarmonyOS是基于OpenHarmony開發的,因此,使用DevEco Studio(配套HarmonyOS)也可以進行
    發表于 10-22 10:35

    OpenHarmony 應用開發快速入門

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

    迅為RK3568開發OpenHarmony v3.2-Beta4 版本測試

    迅為RK3568開發OpenHarmony v3.2-Beta4 版本測試在上個章節,我們在 RK3568 開發板上燒寫了 OpenHarmony 鏡像,本章節我們來對底板外設進行
    發表于 03-29 15:09

    openharmony開發企業有哪些

    將會在各種智能終端上運用。那么openharmony開發企業有哪些?下面小編就為大家帶來openharmony開發企業有哪些的答案。 openhar
    的頭像 發表于 06-23 11:13 ?1869次閱讀

    openharmony開發openharmony開發

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

    使用Python開發OpenHarmony設備程序-I2C應用實例分享

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

    OpenHarmony輕量系統開發【1】初始OH

    的。 后續將給大家陸續分享輕量系統開發相關內容 目錄: OpenHarmony輕量系統開發【1】初始OpenHarmony OpenHarmony
    發表于 02-25 17:49 ?813次閱讀

    openharmony開源社區 OpenHarmony開發樣例上新了

    openharmony開源社區 OpenHarmony開發樣例上新了 OpenHarmony 開源項目是由開放原子開源基金會孵化及運營的開源項目,由開放原子開源基金會
    的頭像 發表于 04-25 16:37 ?2135次閱讀

    OpenHarmony開發體系內容介紹

    初學OpenHarmony,開發者最需要構建對OpenHarmony開發體系的整體了解。
    的頭像 發表于 07-04 10:34 ?1215次閱讀

    OpenHarmony輕量系統書籍推薦《OpenHarmony輕量設備開發理論與實戰》

    最近大家問的智能家居套件方面有沒有可以參考的資料,這里給大家統一回復一下 推薦大家可以看這本書 《OpenHarmony輕量設備開發理論與實戰》 本書系統地講授OpenHarmony 輕量系統 設備
    的頭像 發表于 07-20 12:43 ?692次閱讀

    鴻蒙開發實例:【配置OpenHarmony SDK】

    在設置OpenHarmony應用開發環境時,需要開發者在DevEco Studio中配置對應的SDK信息。
    的頭像 發表于 04-22 15:24 ?259次閱讀
    鴻蒙<b class='flag-5'>開發</b><b class='flag-5'>實例</b>:【配置<b class='flag-5'>OpenHarmony</b> SDK】
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>