HarmonyOS application development-preferences and background notification management

Preferences

Today, as the mobile Internet is booming, mobile applications have brought great convenience to our lives. The essence of these conveniences lies in the interconnection of data. Therefore, data storage plays a very important role in application development, and HarmonyOS application development is no exception. This chapter takes the preferences of HarmonyOS as an example to introduce the data management capabilities of HarmonyOS.

What are preferences

Preferences provide applications with Key-Value key-value data storage capabilities, allowing applications to persist lightweight data and add, delete, modify, and query data. Thedata in this storage object will be cached in memory so it can be accessed faster.

The characteristics of preferences are as follows:

  1. Data stored in Key-Value format: Data is stored in the form of key-value pairs, where Key is the unique keyword and the corresponding Value is the actual data value.

  2. Non-relational database: Unlike relational databases, preferences do not follow ACID properties (Atomicity, Consistency, Isolation, Durability), and there is no relationship between data.

  3. Unique instance in process: Only one instance of a preference exists per file within a process. After the application obtains the instance, it can read data from it or store data in it. By calling the flush method, the data in the instance can be written back to the file.

  4. Differences from relational databases:

    td>

    Characteristics/properties Relational database Preferences
    Data storage format Table (relational) Key-Value (non-relational)
    ACID properties
    Follow ACID Do not follow ACID
    Data relationship There is an association between data tables No data relationship, independent Key-Value pairs
    Storage engine Use database engine, such as SQLite, etc. Stored in file
    Usage scene Complex scene Local database management under Perform simple operations on the data of Key-Value structure
    Data processing Complex query, transaction processing, etc. Simple access and persistence operations
    Restraints and limitations Connection pool size, number of simultaneous write operations, etc. Recommended number of data entries, Key type restrictions

Common interfaces for preferences

Interface Function
< strong>put Store data into preferences
get Get the data value in the preference through the specified Key
has Check whether the given Key is included in the preferences
delete Delete the data of the specified Key from the preferences
flush Write the data in the preferences back to the file to achieve data persistence

Before use, you need to import the @ohos.data.preferences module, name the instance dataPreferences, and define two constants PREFERENCES_NAME and KEY_APP_FONT_SIZE.

// PreferencesUtil.ets
import dataPreferences from '@ohos.data.preferences';
   ...
  const PREFERENCES_NAME = 'myPreferences'; // Preference name
  const KEY_APP_FONT_SIZE = 'appFontSize'; // Preference Key field

It is necessary to obtain the preference instance in the onCreate method of entryAbility so that subsequent operations such as saving, reading, and deleting can be performed. Obtaining the instance requires context and file name PREFERENCES_NAME.

// entryAbility.ets
  onCreate(want, launchParam) {<!-- -->
    Logger.info(TAG, 'onCreate');
    globalThis.abilityWant = want;
    //Create preferences
    PreferencesUtil.createFontPreferences(this.context);
    ...
  }

// PreferencesUtil.ets
  createFontPreferences(context) {<!-- -->
    globalThis.getFontPreferences = (() => {<!-- -->
      // Get preference instance
      let preferences: Promise<dataPreferences.Preferences> = dataPreferences.getPreferences(context, PREFERENCES_NAME);
      return preferences;
    });
  }
</code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">

Save data

In the onCreate method of entryAbility, call PreferencesUtil.saveDefaultFontSize to save the default data. First use the has method to determine whether the current key exists. If not, use the put method to save the user data. This method saves the key-value pair as a constant. KEY_APP_FONT_SIZE is used as key, user data fontSize is used as value, and then the data is saved to the file through the flush method.

// entryAbility.ets
  onCreate(want, launchParam) {<!-- -->
    Logger.info(TAG, 'onCreate');
    globalThis.abilityWant = want;
    ...
    //Set the default font size
    PreferencesUtil.saveDefaultFontSize(Constants.SET_SIZE_STANDARD);
  }
// PreferencesUtil.ets
  saveDefaultFontSize(fontSize: number) {<!-- -->
    globalThis.getFontPreferences().then((preferences) => {<!-- -->
      // Determine whether the saved key exists
      preferences.has(KEY_APP_FONT_SIZE).then(async (isExist) => {<!-- -->
        Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);
        if (!isExist) {<!-- -->
          // save data
          await preferences.put(KEY_APP_FONT_SIZE, fontSize);
          preferences.flush();
        }
      }).catch((err) => {<!-- -->
        Logger.error(TAG, 'Has the value failed with err: ' + err);
      });
    }).catch((err) => {<!-- -->
      Logger.error(TAG, 'Get the preferences failed, err: ' + err);
    });
  }
</code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">

Get data

In the onPageShow method of HomePage, call the PreferencesUtil.getChangeFontSize method to obtain user data, and call the get method to obtain it. This method reads through key-value pairs, with the constant KEY_APP_FONT_SIZE as the key, the default data fontSize as the value, and assigns the result. Give the variable fontSize and return the value through return.

// HomePage.ets
  onPageShow() {<!-- -->
    PreferencesUtil.getChangeFontSize().then((value) => {<!-- -->
      this.changeFontSize = value;
      Logger.info(TAG, 'Get the value of changeFontSize: ' + this.changeFontSize);
    });
  }
// PreferencesUtil.ets
  async getChangeFontSize() {<!-- -->
    let fontSize: number = 0;
    const preferences = await globalThis.getFontPreferences();
    fontSize = await preferences.get(KEY_APP_FONT_SIZE, fontSize);
    return fontSize;
  }

Whether it contains the specified key

Use the has method to determine whether the preference contains the specified key to ensure that the specified key will not be saved repeatedly.

// PreferencesUtil.ets
  saveDefaultFontSize(fontSize: number) {<!-- -->
    globalThis.getFontPreferences().then((preferences) => {<!-- -->
      // Determine whether the saved key exists
      preferences.has(KEY_APP_FONT_SIZE).then(async (isExist) => {<!-- -->
        Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);
      }).catch((err) => {<!-- -->
        Logger.error(TAG, 'Has the value failed with err: ' + err);
      });
    }).catch((err) => {<!-- -->
      Logger.error(TAG, 'Get the preferences failed, err: ' + err);
    });
  }

Data persistence

Use the flush method to save application data to files to extend the retention period of application data.

// PreferencesUtil.ets
  saveChangeFontSize(fontSize: number) {<!-- -->
    globalThis.getFontPreferences().then(async (preferences) => {<!-- -->
      // save data
      await preferences.put(KEY_APP_FONT_SIZE, fontSize);
     //Data persistence
      preferences.flush();
    }).catch((err) => {<!-- -->
      Logger.error(TAG, 'put the preferences failed, err: ' + err);
    });
  }

Delete data

To delete preference data, you need to obtain the preferences instance, use the delete method to delete the value corresponding to the specified key, and use the constant KEY_APP_FONT_SIZE as the key. Use the Promise asynchronous callback to determine whether the deletion is successful.

// PreferencesUtil.ets
  async deleteChangeFontSize() {<!-- -->
    const preferences: dataPreferences.Preferences = await globalThis.getFontPreferences();
    // delete data
    let deleteValue = preferences.delete(KEY_APP_FONT_SIZE);
    deleteValue.then(() => {<!-- -->
      Logger.info(TAG, 'Succeeded in deleting the key appFontSize.');
    }).catch((err) => {<!-- -->
      Logger.error(TAG, 'Failed to delete the key appFontSize. Cause: ' + err);
    });
  }

Background notification management

The role of notification

Notifications are designed to allow users to get timely and useful new information in an appropriate way, helping users handle tasks efficiently. The application can send notification messages through the notification interface. The user can view the notification content through the notification bar, or click on the notification to open the application. The main usage scenarios of notifications are as follows:

  • Display received short messages, instant messages, etc.
  • Display application push messages, such as advertisements, version updates, etc.
  • Displays currently ongoing events, such as downloads, etc.

Notifications will prompt users in different forms in different scenarios. For example, notifications will be displayed as icons on the status bar and notification details will be displayed on the notification bar. Important information can also be displayed as banner notifications floating at the top of the interface.

Create notification

This section will introduce the creation of several common types of notifications. Before creating notifications, you need to import the notificationManager module. This module provides notification management capabilities, including publishing and unpublishing notifications, creation, acquisition, and removal. Notification channels and other capabilities.

import notification from '@ohos.notificationManager';

Basic type notification

Basic type notifications are mainly used to send short messages, prompt messages, advertising push, etc., and support normal text types, Long text type, Multiline text type and Image type, you can specify the content type of the notification through contentType.

To publish a normal text type notification, you need to set the contentType to ContentType.NOTIFICATION_CONTENT_BASIC_TEXT.

import notification from '@ohos.notificationManager';

@Entry
@Component
struct NotificationDemo {<!-- -->
  publishNotification() {<!-- -->
    let notificationRequest: notification.NotificationRequest = {<!-- --> // Describe the notification request
      id: 1, // notification ID
      slotType: notification.SlotType.SERVICE_INFORMATION,
      content: {<!-- --> // Notification content
        contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // Ordinary text type notification
        normal: {<!-- --> // Basic type notification content
          title: 'Notification content title',
          text: 'Notification content details',
          additionalText: 'Notification additional content', // Notification additional content is a supplement to the notification content.
        }
      }
    }
    notification.publish(notificationRequest).then(() => {<!-- --> // Publish notification
      console.info('publish success');
    }).catch((err) => {<!-- -->
      console.error(`publish failed, dcode:${<!-- -->err.code}, message:${<!-- -->err.message}`);
    });
  }

  build() {<!-- -->
    Column() {<!-- -->
      Button('Send notification')
        .onClick(() => {<!-- -->
          this.publishNotification()
        })
    }
    .width('100%')
  }
}
</code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">
Parameter name Function
notificationRequest Describes the request object of the notification, including various information of the notification.
id The unique identifier of the notification, use To distinguish between different notifications.
slotType The slot type of the notification, specify the notification in the notification bar.
content Object containing notification content, specified The type and specific content of the notification.
contentType Specify the content type of the notification, for example Normal text, long text, pictures, etc.
normal Contains the details of normal text type notifications Content information.
title The title of the ordinary text type notification.
text Details of ordinary text type notifications .
additionalText Additional content for ordinary text type notifications , a supplementary explanation of the content of the notice.
publish notification.publish method, used to publish notifications.
then Promise’s success callback, used for The action to perform after the notification is published successfully.
catch Promise’s failure callback, used for Handle error conditions when notification publishing fails.
onClick Button click event handler, Used to trigger a notification publishing action when the button is clicked.

Publish image type notification

To publish a normal text type notification, you need to set the contentType to ContentType.NOTIFICATION_CONTENT_PICTURE.

import notification from '@ohos.notificationManager';
import image from '@ohos.multimedia.image';

@Entry
@Component
struct NotificationTest1 {<!-- -->
  async publishPictureNotification() {<!-- -->
    // Convert resource images into PixelMap objects
    let resourceManager = getContext(this).resourceManager;
    let imageArray = await resourceManager.getMediaContent($r('app.media.bigPicture').id);
    let imageResource = image.createImageSource(imageArray.buffer);
    let pixelMap = await imageResource.createPixelMap();

    let notificationRequest: notification.NotificationRequest = {<!-- --> // Describe the notification request
      id: 1,
      content: {<!-- -->
        contentType: notification.ContentType.NOTIFICATION_CONTENT_PICTURE,
        picture: {<!-- -->
          title: 'Good things are on sale', // Notification content title
          text: 'Expand to view details', // Notification content
          expandedTitle: 'Today's Hot Recommendations', // Content title when the notification is expanded
          briefText: 'There must be something you like here', // The summary content of the notification is a summary of the content of the notification
          picture: pixelMap // Picture content of notification
        }
      }
    }

    notification.publish(notificationRequest).then(() => {<!-- --> // Publish notification
      console.info('publish success');
    }).catch((err) => {<!-- -->
      console.error(`publish failed, dcode:${<!-- -->err.code}, message:${<!-- -->err.message}`);
    });
  }

  build() {<!-- -->
    Column() {<!-- -->
      Button('Send large image notification')
        .onClick(() => {<!-- -->
          this.publishPictureNotification()
        })
    }
    .width('100%')
  }
}
</code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">
Parameter name Function
notificationRequest Describes the request object of the notification, including various information of the notification.
id The unique identifier of the notification, used to distinguish different notifications.
content An object containing notification content, specifying the type and specific content of the notification.
contentType Specify the content type of the notification, such as pictures, normal text, long text wait.
picture Contains specific content information of the picture type notification.
title The title of the picture type notification.
text Details of the image type notification.
expandedTitle The content title when the image type notification is expanded.
briefText The summary content of the image type notification, a summary of the notification content.
picture The picture content of the picture type notification.
pixelMap Notified image content, through pixel map (pixelMap) means.
publish notification.publish method, used Post a notice.
then Promise’s success callback, used to execute after the notification is released successfully. operate.
catch Promise’s failure callback, used to handle errors when notification publishing fails Condition.
onClick Button click event handler, used to trigger when the button is clicked Notification publishing operation.

Progress type notification

Progress bar notifications are also a common type of notifications and are mainly used to display the progress of file download and transaction processing. Currently, the system template only supports progress bar templates.

  • Before publishing a progress type notification, you need to check whether the system supports the progress bar template.

    notification.isSupportTemplate('downloadTemplate').then((data) => {<!-- -->
      console.info(`[ANS] isSupportTemplate success`);
      let isSupportTpl: boolean = data; // The value of isSupportTpl is true to indicate that the downloadTemplate template class notification is supported, and false to indicate that it is not supported.
      // ...
    }).catch((err) => {<!-- -->
      console.error(`[ANS] isSupportTemplate failed, error[${<!-- -->err}]`);
    });
    
  • Construct a progress bar template. The name field currently needs to be configured as downloadTemplate.

    let template = {<!-- -->
     name: 'downloadTemplate',
     data: {<!-- -->
       progressValue: 60, // current progress value
       progressMaxValue: 100 // Maximum progress value
      }
    }
    
    let notificationRequest = {<!-- -->
     id: 1,
     content: {<!-- -->
       contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
       normal: {<!-- -->
         title: 'File download: music.mp4',
         text: 'senTemplate',
         additionalText: '60%'
       }
     },
      template: template
    }
    // Publish notification
    notification.publish(notificationRequest).then(() => {<!-- -->
     console.info(`publish success`);
    }).catch(error => {<!-- -->
     console.error(`[ANS] publish failed, code is ${<!-- -->error.code}, message is ${<!-- -->error.message}`);
    })
    </code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">

Update notification

After sending the notification, call notification.publish again using the same notification ID you used before to update the notification. If the previous notification was closed, a new notification will be created.

Removal notification

//Cancel a published notification by notification ID
notification.cancel(notificationId)
// Cancel all published notifications
notification.cancelAll()

Notification channel

Through the notification channel, you can let notifications have different presentation forms. For example, social notifications are displayed with banners and have prompt sounds, while general notifications are not displayed with banners. You can use slotType to fulfill.

td>

td>

td>

Notification channel type Show notification icon Show banner Beep sound Applicable scenarios
SlotType.SOCIAL_COMMUNICATION Yes Yes Yes Social applications, such as messaging, social media, etc., require users to pay attention and respond in a timely manner.
SlotType.SERVICE_INFORMATION Yes No Yes Service applications, such as background service status, system information, etc., do not require overly conspicuous prompts.
SlotType.CONTENT_INFORMATION Yes No No Content-related applications, such as news, article updates, etc., users are more concerned about the content of notifications rather than timely responses.
SlotType.OTHER_TYPES No No No There is no need to display the icon in the status bar, and the notification content does not need to attract the user’s attention.

Backend agent reminder

This section describes the basic operations of using background agent reminder (reminderAgentManager) to add, publish, delete and modify reminders in HarmonyOS applications.

There are mainly the following types of background agent reminders:

  • Countdown
  • calendar
  • Alarm clock

Add usage rights

"module": {<!-- -->
  ...
  "requestPermissions": [
    {<!-- -->
      "name": "ohos.permission.PUBLISH_AGENT_REMINDER"
    }
  ]
}

Added permission to use background proxy reminders in the application’s module configuration.

Import reminderAgent module

import reminderAgent from '@ohos.reminderAgentManager';

Import the background agent reminder module through the @ohos.reminderAgentManager module and name it reminderAgent.

Add reminder

export class ReminderService {<!-- -->
  public addReminder(alarmItem: ReminderItem, callback?: (reminderId: number) => void) {<!-- -->
    let reminder = this.initReminder(alarmItem);
    reminderAgent.publishReminder(reminder, (err, reminderId) => {<!-- -->
      if (callback != null) {<!-- -->
        callback(reminderId);
      }
    });
  }
}

Use the reminderAgent.publishReminder method to publish a new reminder. The specific information of the reminder is defined by the ReminderRequestAlarm type.

Delete Reminder

export class ReminderService {<!-- -->
  public deleteReminder(reminderId: number) {<!-- -->
    reminderAgent.cancelReminder(reminderId);
  }
}

Use the reminderAgent.cancelReminder method to delete a reminder with the specified reminderId.

Modification reminder

public async setAlarmRemind(alarmItem: AlarmItem) {<!-- -->
  let index = await this.findAlarmWithId(alarmItem.id);
  if (index !== Constants.DEFAULT_NUMBER_NEGATIVE) {<!-- -->
    this.reminderService.deleteReminder(alarmItem.id);
  } else {<!-- -->
    // Process logic for adding new reminders
  }

  this.reminderService.addReminder(alarmItem, (newId) => {<!-- -->
    alarmItem.id = newId;
    // Logic for handling new reminders
  })
}

When modifying a reminder, first call the deleteReminder method to delete the old reminder, and then call the addReminder method to add a new reminder.