鸿蒙开发5.0【应用异常处理】运维

应用异常处理

介绍

本示例介绍了通过应用事件打点hiAppEvent获取上一次应用异常信息的方法,主要分为应用崩溃、应用卡死两种。

效果图预览

1

使用说明

  1. 点击构建应用崩溃事件,3s之后应用退出,然后打开应用进入应用异常页面,隔1min左右后,显示上次异常退出信息。
  2. 点击构建应用卡死事件,需手动退出,然后打开应用进入应用异常页面,隔1min左右后,显示上次异常退出信息。

实现思路

  1. 构建应用异常。源码参考[Index.ets]
/** Copyright (c) 2024 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 { hiAppEvent } from '@kit.PerformanceAnalysisKit';
import { PreferencesManager } from '../model/PreferencesManager';
import { BUTTON_TEXT } from '../model/MockData';
import { FaultDataSource } from '../model/DataSource';
import { Logger } from '../log/Logger';const TAG: string = 'FaultLogger'; // Abnormal Application Page Tag
const DELAY_TIME: number = 3000;@Entry
@Component
struct ApplicationExceptionView {// Initialize the index of the clicked exception event@Provide eventIndex: number = -1;build() {Column() {// Scenario description componentFunctionDescription({title: $r('app.string.application_exception_application_fault_title'),content: $r('app.string.application_exception_application_fault_description')})// Abnormal information display componentFaultArea()// Constructing Abnormal ComponentsFaultConstruction()}.padding($r('app.string.ohos_id_card_padding_start')).backgroundColor($r('app.color.ohos_id_color_sub_background')).width($r('app.string.ohos_global_state_dialog_hundred_percent')).height($r('app.string.ohos_global_state_dialog_hundred_percent')).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])}
}@Component
struct FaultArea {// Perform bidirectional data binding on the array length of lazy loading data sources@StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;// Bidirectional data binding event group, bound to AppStorage. setOrCreate,// this variable changes and triggers the getFaultMessage function@StorageLink('appEventGroups') @Watch('getFaultMessage') appEventGroups: Array<hiAppEvent.AppEventGroup> = [];// Abnormal trigger sign@StorageLink('faultSign') faultSign: boolean = false;// The index of the clicked abnormal event@Consume eventIndex: number;// Data source for lazy loading@State faultDataSource: FaultDataSource = new FaultDataSource();private scroller: Scroller = new Scroller();async aboutToAppear() {Logger.info(TAG, `aboutToAppear start`);// Get Preferences instanceawait PreferencesManager.getPreferences(this.faultDataSource);// First, retrieve data from the persistent storage,// then add the previous application exception information to the list header,// and update the persistent storagethis.getFaultMessage();// Reset appEventGroups in AppStorage to avoid adding duplicate dataAppStorage.setOrCreate('appEventGroups', []);}// Obtain application exception informationasync getFaultMessage() {Logger.info(TAG, `getAppEventGroups start`);if (this.appEventGroups && this.appEventGroups.length > 0) {// Traverse event groupsthis.appEventGroups.forEach((eventGroup: hiAppEvent.AppEventGroup) => {// Traverse the collection of event objectseventGroup.appEventInfos.forEach(async (eventInfo: hiAppEvent.AppEventInfo) => {let message: string = '';message += `HiAppEvent eventInfo.domain=${eventInfo.domain}\n`+ `HiAppEvent eventInfo.name=${eventInfo.name}\n`+ `HiAppEvent eventInfo.eventType=${eventInfo.eventType}\n`+ `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}\n`+ `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}\n`+ `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}\n`+ `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}\n`+ `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}\n`+ `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}\n`+ `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}\n`;// Knowledge point: Storing exception information in the array faultMessagethis.faultDataSource.pushData(message);})})}// Knowledge point: Persisting storage exception information collectionthis.faultDataSource.persistenceStorage();}build() {List({ scroller:this.scroller }) {// Add a judgment, if the number of information in the set of abnormal information is greater than 0, traverse the abnormal informationif (this.faultDataSourceLength > 0) {LazyForEach(this.faultDataSource, (message: string) => {ListItem() {Text(message).textAlign(TextAlign.Start)}}, (item: string) => item)} else {ListItem() {// Respond to specified information based on the index of the clicked eventText(this.eventIndex === 0 ? $r('app.string.application_exception_crash_event_message') :(this.eventIndex === 1 ? $r('app.string.application_exception_freeze_event_message') :(this.faultSign ? $r('app.string.application_exception_data_delay_toast') :$r('app.string.application_exception_no_message'))))}}}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).height($r('app.string.ohos_id_elements_list_high')).borderRadius($r('app.string.ohos_id_corner_radius_default_m')).padding($r('app.string.ohos_id_card_padding_start')).margin({ top: $r('app.string.ohos_id_elements_margin_vertical_l') }).backgroundColor(Color.White)}
}@Component
struct FaultConstruction {// The index of the clicked abnormal event@Consume eventIndex: number;// Perform bidirectional data binding on the array length of lazy loading data sources@StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;// Abnormal trigger sign@StorageLink('faultSign') faultSign: boolean = false;handleOperate(index: number) {switch (index) {case 0:// Note: This is a deliberately constructed bug// Construct an APP-CRASH scenario in the button click function to trigger an application crash eventconst result: object = JSON.parse('');break;case 1:// Note: This is a deliberately constructed bug// Construct an APP-FREEZE scenario in the button click function,// trigger the application freeze event, and execute an infinite loop after 500mswhile (true) {}default:break;}}build() {Stack() {Column(){ForEach(BUTTON_TEXT, (item: string, index: number) => {Button(item).type(ButtonType.Capsule).size({ width: $r('app.string.ohos_global_state_dialog_hundred_percent') }).borderRadius($r('app.string.ohos_id_corner_radius_default_m')).margin({ top: $r('app.string.ohos_id_button_margin_top') }).onClick(() => {// Abnormal trigger signthis.faultSign = true;PreferencesManager.putFaultSign();// When clicking on an exception, clear the page information data// and display the exception description information.// To control the display of page information data,// this variable needs to be set to 0this.faultDataSourceLength = 0;// Update the index of clicked abnormal eventsthis.eventIndex = index;// Execute system crash operation after 3ssetTimeout(() => {this.handleOperate(index);}, DELAY_TIME);})}, (item: string) => JSON.stringify(item))}.width($r('app.string.ohos_global_state_dialog_hundred_percent'))}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).margin({ bottom: $r('app.string.ohos_id_button_margin_bottom')}).align(Alignment.Bottom).flexGrow(1)}
}@Component
struct FunctionDescription {private title: ResourceStr = '';private content: ResourceStr = '';build() {Column() {Row() {Text(this.title).fontSize($r('app.string.ohos_id_text_size_headline')).fontWeight(FontWeight.Medium).textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(1)}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).margin({ bottom: $r('app.string.ohos_id_elements_margin_vertical_m') })Row() {Text(this.content).wordBreak(WordBreak.NORMAL)}.width($r('app.string.ohos_global_state_dialog_hundred_percent'))}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).padding($r('app.string.ohos_id_card_padding_start'))}
}
  1. 应用退出后,进入本页面,等待订阅消息通知,待收到订阅消息后,通过EventSubscription.ets中的onReceive函数,接收到异常信息数据,并通过AppStorage.setOrCreate(‘appEventGroups’,异常信息数据)双向绑定异常信息,源码参考代码可参考[EventSubscription.ets]
/** Copyright (c) 2024 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 { hiAppEvent } from '@kit.PerformanceAnalysisKit';
import { Logger } from '../log/Logger';const TAG: string = 'eventSubscription';export function eventSubscription(): void {// Add application event observer method, which can be used to subscribe to application eventshiAppEvent.addWatcher({// Developers can customize observer names, which the system will use to identify different observersname: 'mst',// Developers can subscribe to system events of interest, where they have subscribed to crash eventsappEventFilters: [{domain: hiAppEvent.domain.OS,names: [hiAppEvent.event.APP_CRASH, hiAppEvent.event.APP_FREEZE]}],// Knowledge point: Obtain event group information.// Developers can implement subscription callback functions themselves,// and crash and freeze events will be called back to developers the next time the application startsonReceive: async (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {Logger.info(TAG, `HiAppEvent onReceive: domain=${domain}`);// Obtain event group information and perform bidirectional data binding with// @StorageLink('faultMessage') faultMessage in the ApplicationException file// Performance concerns: If developers have synchronized code that requires time-consuming operations,// it is recommended to start worker or taskpool threads to handle it.// But if developers use storage and preferences, they can simply call them.AppStorage.setOrCreate('appEventGroups', appEventGroups);}});
}
  1. @StorageLink(‘appEventGroups’)接收订阅事件函数传递的事件组信息,调用getFaultMessage函数对信息进行处理,将处理后的信息通过 this.faultDataSource.pushData(message) 添加到懒加载数据源中,并通过this.faultDataSource.persistenceStorage()执行持久化存储,最后通过使用LazyForEach将数据信息加载到页面上。具体源码参考[Index.ets]
/** Copyright (c) 2024 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 { hiAppEvent } from '@kit.PerformanceAnalysisKit';
import { PreferencesManager } from '../model/PreferencesManager';
import { BUTTON_TEXT } from '../model/MockData';
import { FaultDataSource } from '../model/DataSource';
import { Logger } from '../log/Logger';const TAG: string = 'FaultLogger'; // Abnormal Application Page Tag
const DELAY_TIME: number = 3000;@Entry
@Component
struct ApplicationExceptionView {// Initialize the index of the clicked exception event@Provide eventIndex: number = -1;build() {Column() {// Scenario description componentFunctionDescription({title: $r('app.string.application_exception_application_fault_title'),content: $r('app.string.application_exception_application_fault_description')})// Abnormal information display componentFaultArea()// Constructing Abnormal ComponentsFaultConstruction()}.padding($r('app.string.ohos_id_card_padding_start')).backgroundColor($r('app.color.ohos_id_color_sub_background')).width($r('app.string.ohos_global_state_dialog_hundred_percent')).height($r('app.string.ohos_global_state_dialog_hundred_percent')).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])}
}@Component
struct FaultArea {// Perform bidirectional data binding on the array length of lazy loading data sources@StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;// Bidirectional data binding event group, bound to AppStorage. setOrCreate,// this variable changes and triggers the getFaultMessage function@StorageLink('appEventGroups') @Watch('getFaultMessage') appEventGroups: Array<hiAppEvent.AppEventGroup> = [];// Abnormal trigger sign@StorageLink('faultSign') faultSign: boolean = false;// The index of the clicked abnormal event@Consume eventIndex: number;// Data source for lazy loading@State faultDataSource: FaultDataSource = new FaultDataSource();private scroller: Scroller = new Scroller();async aboutToAppear() {Logger.info(TAG, `aboutToAppear start`);// Get Preferences instanceawait PreferencesManager.getPreferences(this.faultDataSource);// First, retrieve data from the persistent storage,// then add the previous application exception information to the list header,// and update the persistent storagethis.getFaultMessage();// Reset appEventGroups in AppStorage to avoid adding duplicate dataAppStorage.setOrCreate('appEventGroups', []);}// Obtain application exception informationasync getFaultMessage() {Logger.info(TAG, `getAppEventGroups start`);if (this.appEventGroups && this.appEventGroups.length > 0) {// Traverse event groupsthis.appEventGroups.forEach((eventGroup: hiAppEvent.AppEventGroup) => {// Traverse the collection of event objectseventGroup.appEventInfos.forEach(async (eventInfo: hiAppEvent.AppEventInfo) => {let message: string = '';message += `HiAppEvent eventInfo.domain=${eventInfo.domain}\n`+ `HiAppEvent eventInfo.name=${eventInfo.name}\n`+ `HiAppEvent eventInfo.eventType=${eventInfo.eventType}\n`+ `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}\n`+ `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}\n`+ `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}\n`+ `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}\n`+ `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}\n`+ `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}\n`+ `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}\n`;// Knowledge point: Storing exception information in the array faultMessagethis.faultDataSource.pushData(message);})})}// Knowledge point: Persisting storage exception information collectionthis.faultDataSource.persistenceStorage();}build() {List({ scroller:this.scroller }) {// Add a judgment, if the number of information in the set of abnormal information is greater than 0, traverse the abnormal informationif (this.faultDataSourceLength > 0) {LazyForEach(this.faultDataSource, (message: string) => {ListItem() {Text(message).textAlign(TextAlign.Start)}}, (item: string) => item)} else {ListItem() {// Respond to specified information based on the index of the clicked eventText(this.eventIndex === 0 ? $r('app.string.application_exception_crash_event_message') :(this.eventIndex === 1 ? $r('app.string.application_exception_freeze_event_message') :(this.faultSign ? $r('app.string.application_exception_data_delay_toast') :$r('app.string.application_exception_no_message'))))}}}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).height($r('app.string.ohos_id_elements_list_high')).borderRadius($r('app.string.ohos_id_corner_radius_default_m')).padding($r('app.string.ohos_id_card_padding_start')).margin({ top: $r('app.string.ohos_id_elements_margin_vertical_l') }).backgroundColor(Color.White)}
}@Component
struct FaultConstruction {// The index of the clicked abnormal event@Consume eventIndex: number;// Perform bidirectional data binding on the array length of lazy loading data sources@StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;// Abnormal trigger sign@StorageLink('faultSign') faultSign: boolean = false;handleOperate(index: number) {switch (index) {case 0:// Note: This is a deliberately constructed bug// Construct an APP-CRASH scenario in the button click function to trigger an application crash eventconst result: object = JSON.parse('');break;case 1:// Note: This is a deliberately constructed bug// Construct an APP-FREEZE scenario in the button click function,// trigger the application freeze event, and execute an infinite loop after 500mswhile (true) {}default:break;}}build() {Stack() {Column(){ForEach(BUTTON_TEXT, (item: string, index: number) => {Button(item).type(ButtonType.Capsule).size({ width: $r('app.string.ohos_global_state_dialog_hundred_percent') }).borderRadius($r('app.string.ohos_id_corner_radius_default_m')).margin({ top: $r('app.string.ohos_id_button_margin_top') }).onClick(() => {// Abnormal trigger signthis.faultSign = true;PreferencesManager.putFaultSign();// When clicking on an exception, clear the page information data// and display the exception description information.// To control the display of page information data,// this variable needs to be set to 0this.faultDataSourceLength = 0;// Update the index of clicked abnormal eventsthis.eventIndex = index;// Execute system crash operation after 3ssetTimeout(() => {this.handleOperate(index);}, DELAY_TIME);})}, (item: string) => JSON.stringify(item))}.width($r('app.string.ohos_global_state_dialog_hundred_percent'))}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).margin({ bottom: $r('app.string.ohos_id_button_margin_bottom')}).align(Alignment.Bottom).flexGrow(1)}
}@Component
struct FunctionDescription {private title: ResourceStr = '';private content: ResourceStr = '';build() {Column() {Row() {Text(this.title).fontSize($r('app.string.ohos_id_text_size_headline')).fontWeight(FontWeight.Medium).textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(1)}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).margin({ bottom: $r('app.string.ohos_id_elements_margin_vertical_m') })Row() {Text(this.content).wordBreak(WordBreak.NORMAL)}.width($r('app.string.ohos_global_state_dialog_hundred_percent'))}.width($r('app.string.ohos_global_state_dialog_hundred_percent')).padding($r('app.string.ohos_id_card_padding_start'))}
}
  1. 以上代码中有引用懒加载数据类和持久化存储类,源码可参考[DataSource.ets]
/** Copyright (c) 2024 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 { PreferencesManager } from './PreferencesManager';// Basic implementation of IDataSource to handle data listener
class BasicDataSource implements IDataSource {// Data change listenerprivate listeners: DataChangeListener[] = [];// Data sources that require data iterationprivate originDataArray: string[] = [];// Obtain the length of datapublic totalCount(): number {return 0;}// Get specified data itemspublic getData(index: number): string {return this.originDataArray[index];}// This method is called on the framework side to add a listener listener// to the LazyForEach component's data source for listeningregisterDataChangeListener(listener: DataChangeListener): void {if (this.listeners.indexOf(listener) < 0) {console.info('add listener');this.listeners.push(listener);}}// This method is called on the framework side to remove listener listening// at the data source for the corresponding LazyForEach componentunregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener);if (pos >= 0) {console.info('remove listener');this.listeners.splice(pos, 1);}}// Notify LazyForEach component to overload all child componentsnotifyDataReload(): void {this.listeners.forEach(listener => {listener.onDataReloaded();})}// Notify LazyForEach component to add sub components at// the index corresponding to the indexnotifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDataAdd(index);})}// Notify the LazyForEach component that there is a change in data at// the index corresponding to the index, and that the subcomponent needs to be rebuiltnotifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDataChange(index);})}// Notify LazyForEach component to delete the subcomponent at the index corresponding to the indexnotifyDataDelete(index: number): void {this.listeners.forEach(listener => {listener.onDataDelete(index);})}
}export class FaultDataSource extends BasicDataSource {// Lazy loading dataprivate faultMessage: Array<string> = [];// Knowledge point: Obtaining the data length of lazy loading data sourcestotalCount(): number {return this.faultMessage.length;}// Get specified data itemsgetData(index: number): string {return this.faultMessage[index];}// Knowledge point: Storing data into lazy loading data sourcespushData(data: string): void {this.faultMessage.unshift(data);// Add data to the array headerthis.notifyDataAdd(0);AppStorage.setOrCreate('faultDataSourceLength', this.totalCount());}// Knowledge point: Persisting storage exception information collectionpersistenceStorage(): void {PreferencesManager.putFaultMessage(this.faultMessage);}
}

和参考源码:[PreferencesManager.ets]

/** Copyright (c) 2024 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 { preferences as dataPreferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import { FaultDataSource } from '../model/DataSource';
import { Logger } from '../log/Logger';// Knowledge point: Initialize Preferences instances for persistent storage of
//  exception information and the ability to retrieve persistent data
let dataPreferencesManager: dataPreferences.Preferences = {} as dataPreferences.Preferences;export class PreferencesManager {// Get Preferences instancepublic static async getPreferences(faultDataSource: FaultDataSource): Promise<void> {Logger.info('getPreferences start.');try {let val: dataPreferences.Preferences = await (dataPreferences.getPreferences(AppStorage.get('context'),'myStore') as Promise<dataPreferences.Preferences>);dataPreferencesManager = val;Logger.info('Succeeded in getting preferences.');// Get abnormal informationawait PreferencesManager.getFaultMessage(faultDataSource);await PreferencesManager.getFaultSign();} catch (err) {Logger.error('Failed to get preferences');}}/*** Storing abnormal data information* @Param faultMessage exception information set*/public static async putFaultMessage(faultMessage: Array<string>): Promise<void> {Logger.info(`putMessage start`);try {// Knowledge point: Storing data through the dataPreferencesManager.put methoddataPreferencesManager.put('faultMessage', JSON.stringify(faultMessage), async (err: BusinessError) => {if (err) {Logger.error(`Failed to put value of 'faultMessage'. code =` + err.code + ', message =' + err.message);return;}Logger.info('Succeeded in putting value of faultMessage.');dataPreferencesManager.flush();})} catch (err) {Logger.error(`Failed to put value of 'catch err'. code =` + err.code + ', message =' + err.message);}}/*** Get abnormal data information* @Param faultMessage exception information set*/public static async getFaultMessage(faultDataSource: FaultDataSource): Promise<void> {Logger.info(`getFaultMessage start`);try {// Knowledge point: Obtaining abnormal information data through the dataPreferencesManager.get methodconst data: dataPreferences.ValueType = await dataPreferencesManager.get('faultMessage', []);if (typeof data === 'string') {const faultData: Array<string> = JSON.parse(data);// Add abnormal data to lazy loading data sourcefaultData.forEach((item: string) => {faultDataSource.pushData(item);})// Bidirectional data binding lazy loading data source length, updating data source lengthAppStorage.setOrCreate('faultDataSourceLength', faultDataSource.totalCount());Logger.info('Succeeded in getting value of faultMessage.');}} catch (err) {Logger.error(`Failed to get value of 'catch err'. code =` + err.code + ', message =' + err.message);}}/*** Storage data sign*/public static async putFaultSign(): Promise<void> {Logger.info(`putMessage start`);try {// Knowledge point: Storing data through the dataPreferencesManager.put methoddataPreferencesManager.put('faultSign', JSON.stringify(true), async (err: BusinessError) => {if (err) {Logger.error(`Failed to put value of 'faultSign'. code =` + err.code + ', message =' + err.message);return;}Logger.info('Succeeded in putting value of faultSign.');dataPreferencesManager.flush();})} catch (err) {Logger.error(`putFaultSign Failed to put value of 'catch err'. code =` + err.code + ', message =' + err.message);}}/*** Get abnormal data information*/public static async getFaultSign(): Promise<void> {Logger.info(`getFaultMessage start`);let faultSign: boolean = false;try {// Knowledge point: Obtain exception identifiers through the dataPreferencesManager.get methodconst data: dataPreferences.ValueType = await dataPreferencesManager.get('faultSign', faultSign);if (typeof data === 'string') {faultSign = JSON.parse(data);AppStorage.setOrCreate('faultSign', faultSign);}} catch (err) {Logger.error(`getFaultSign Failed to get value of 'catch err'. code =` + err.code + ', message =' + err.message);}}
}

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/395308.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pdf怎么加密码怎么设置密码?pdf加密码的几种设置方法

在数字化时代&#xff0c;信息的保密性与安全性日益成为我们不可忽视的重要环节。尤其对于包含敏感信息或个人隐私的PDF文档而言&#xff0c;保护其免受未授权访问的侵扰显得尤为重要。通过为PDF文档设置密码保护&#xff0c;我们能够筑起一道坚实的防线&#xff0c;确保只有拥…

Java常见面试题-13-FastDFS

文章目录 FastDFS 是什么&#xff1f;FastDFS 组成FastDFS 的流程FastDFS 如何现在组内的多个 storage server 的数据同步&#xff1f; FastDFS 是什么&#xff1f; FastDFS 是一个开源的轻量级分布式文件系统&#xff0c;它可以对文件进行管理&#xff0c;功能包括&#xff1…

创意指南丨VR游览沉浸式空间体验

欢迎来到我们制作的VR幻想世界。玩家的起点是一条蓝色水晶大道&#xff0c;让我们一起探索这个如梦似幻的境地。 在这条大道的两侧&#xff0c;漂浮着半透明的大水晶水母。它们轻盈地在空中飘动&#xff0c;仿佛在欢迎我们的到来。这条道路上方&#xff0c;一个个半圆环不停地…

【数据结构】Map与Set

前言 前两篇文章我们研究了二叉搜索树与哈希表的结构与特点&#xff0c;他们二者是Map与Set这两个接口实现的底层结构&#xff0c;他们利用了搜索树与哈希表查找效率高这一特点&#xff0c;是一种专门用来进行搜索操作的容器或数据结构。本篇文章就让我们一起来梳理这两个接口的…

基于Hadoop的国内手机销售大数据分析与可视化研究【百万数据集】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍 绪论研究背景研究目的研究意义 相关技术理论介绍Hadoop相关理论HIve数据仓库flume组件介绍sqoop组件介绍Pyecharts介绍 数据来源及处理数据介绍数据预处理 Hadoop集群搭建Hadoop全…

开源wiki知识库工具zyplayer-doc

zyplayer-doc是一款适合团队和个人私有化部署使用的在线知识库、笔记、WIKI文档管理工具。它不仅提供了知识库管理的基本功能&#xff0c;还包含了数据库管理、API接口管理等模块&#xff0c;能够满足用户多样化的需求。 体验地址&#xff1a;文档管理系统 仓库地址&#xff…

Together规则引擎 金融解决方案

目录 1.金融法规和期望正在发生变化,快速跟踪您的金融数字化变革&#xff01;2.抵押贷款功能集&#xff08;MFS&#xff09;3.MFS 示例模型4.MFS 知识特点5.MFS特定功能 1.金融法规和期望正在发生变化,快速跟踪您的金融数字化变革&#xff01; ogether规则引擎使金融机构能够简…

NAT、服务代理、内网穿透

文章目录 NAT技术NAT IP转换过程NATPNAT的优点NAT的缺点 代理服务器正向代理反向代理 内网穿透和内网打洞内网穿透内网穿透 NAT技术 NAT技术即网络地址转换技术。用于将私有IP地址转换为公共IP地址&#xff0c;以便在互联网或其他外部网络中通信。为了解决IPv4协议下IP地址不足…

[matlab] 鲸鱼优化算法优化KNN分类器的特征选择

目录 引言 智能优化算法概述 智能优化算法在KNN特征选择中的应用 应用步骤 UCI数据集 鲸鱼优化算法 一、算法背景与原理 二、算法组成与步骤 三、算法特点与优势 四、应用与挑战 代码实现 鲸鱼优化算法 主程序 打印结果 引言 智能优化算法在优化KNN&#xff08;…

最大耗散功率

注&#xff1a;本文内容来自ChatGPT 最大耗散功率&#xff08;Maximum Power Dissipation&#xff09;是指芯片或电子元件在指定的工作条件下&#xff0c;能够安全散发的最大热功率&#xff0c;通常以瓦特&#xff08;W&#xff09;为单位表示。这是一个关键的设计参数&#x…

什么是Stable Diffusion?如何安装Stable Diffusion?

前言 Stable Diffusion秋叶整合包&#xff0c;一键安装Stable Diffusion&#xff0c;门槛极低&#xff0c;完全免费&#xff0c;支持Nvidia全系列显卡。 来自B站up主秋葉aaaki近期推出的Stable Diffusion整合包v4.6版本&#xff0c;能够让零基础用户轻松在本地部署Stable Diff…

Scanner类、String类和StringBuffer类的相关使用

一、Scanner: 主要用于键盘录入的 构造方法&#xff1a; Scanner(InputStream source) 构造一个新的 Scanner &#xff0c;产生从指定输入流扫描的值。 1、next()和nextLine()区别&#xff1a; String line sc.next(); // 不会接收特殊字符&#xff0c;比如空格回…

Python中的 `continue` 语句:掌握循环控制的艺术

Python中的 continue 语句&#xff1a;掌握循环控制的艺术 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通…

服务器数据恢复—Raid故障导致存储中数据库数据丢失的数据恢复案例

服务器存储数据恢复环境&故障情况&#xff1a; 一台光纤存储中有一组由16块硬盘组成的raid。 该存储出现故障导致数据丢失。RAID中2块盘掉线&#xff0c;还有1块盘smart状态为“警告”。 服务器存储数据恢复过程&#xff1a; 1、通过该存储自带的存储管理软件将当前存储的完…

企业常用的文件加密软件排行榜,10款顶级文件加密软件推荐

在数字化时代&#xff0c;企业数据的安全性和保密性显得尤为重要。为了确保敏感文件不被未授权访问或泄露&#xff0c;企业纷纷采用文件加密软件来加强数据保护。以下是2024年企业常用的10款顶级文件加密软件推荐&#xff0c;它们各具特色&#xff0c;能够满足不同企业的需求。…

【第十届泰迪杯数据挖掘挑战赛A题害虫识别】-农田害虫检测识别-高精度完整更新

农田害虫检测识别项目-高精度完整版 一、说明&#xff1a; 该版本为基于泰迪杯完整害虫数据重新制作数据集、优化增强数据集、重新进行模型训练&#xff0c;达到高精度、高召回率的最优模型代码。包含论文、最优模型文件以及相关文件、原始数据集、训练数据集XML版、增强扩充…

【数据结构】哈希应用-海量数据处理

目录 1、10亿个整数里面求最大的100个 2、求大文件交集 3、查找出现次数前210的ip地址 1、10亿个整数里面求最大的100个 经典的tok问题&#xff0c;可以使用堆来解决 2、求大文件交集 给两个文件&#xff0c;分别有100亿个query&#xff0c;我们只有1G内存&#xff0c;如…

如何用 CocosCreator 对接抖音小游戏的侧边栏复访

前言 最近小游戏的软著下来了&#xff0c;用 CocosCreator 做的游戏也完成了 1.0 版本。而当我打包成抖音小游戏进行提交时&#xff0c;还没到初审就给拒了&#xff0c;因为还有一个机审&#xff0c;机器检测到代码中没有接入 “侧边栏复访功能”。这个我还真不知道&#xff0…

不要问人工智能能为你做什么,而要问你能用人工智能实现什么?

​新前沿 欢迎来到雲闪世界。在过去的一年半里&#xff0c;我一直在向我认识的每个人讲述人工智能的潜力&#xff0c;尤其是大型语言模型 (LLM)。无论技术背景如何&#xff0c;现在是时候让每个人学习 LLM 的基础知识以及如何有效地使用它们了。 20 世纪 60 年代&#xff0c;我…

美国服务器稳定么?影响服务器稳定性的6个因素

美国服务器稳定么&#xff1f;美国服务器的稳定性是相当不错的&#xff0c;这主要得益于其先进的技术、成熟的基础设施以及严格的管理措施。美国拥有众多知名的服务器提供商&#xff0c;这些提供商通常会采用顶级的硬件设施&#xff0c;如英特尔、AMD等知名品牌的处理器&#x…