DEV Community

SameX
SameX

Posted on

In-depth Revelation of HarmonyOS Next Security Controls: A Comprehensive Analysis of Paste and Save Controls

This article aims to deeply explore the technical details of the Huawei HarmonyOS Next system (up to API 12 as of now) in developing multilingual e-commerce platforms, and is summarized based on actual development practices. It mainly serves as a vehicle for technical sharing and communication. Mistakes and omissions are inevitable. Colleagues are welcome to put forward valuable opinions and questions so that we can make progress together. This article is original content, and any form of reprint must indicate the source and the original author.
In the security system of HarmonyOS Next, security controls play a crucial role, providing applications with convenient and secure ways of user interaction and effectively protecting user privacy. Today, we will focus on the paste control and the save control among them, and conduct an in-depth analysis of their functions and usage methods.

I. Paste Control: Simplifying the Reading of Clipboard Data

(I) The Function of the Paste Control

The paste control is a special system security control. Its main function is to enable applications to read clipboard data without prompts under the condition that the user has authorized it. In daily use, we often need to copy and paste information between different applications, such as copying verification codes, text paragraphs, etc. The emergence of the paste control makes this process smoother and more convenient, while also ensuring the security of user data. It is like a bridge that safely transfers the data in the clipboard to the application under the premise of explicit authorization by the user, avoiding the interference of pop-up prompts on the user's operation.

(II) The Method of Reading Clipboard Data Using the Paste Control

  1. Import Dependencies First, import the dependency modules related to the clipboard in the application's code file. For example:
import { pasteboard } from '@kit.BasicServicesKit';
Enter fullscreen mode Exit fullscreen mode

This step is like preparing the tools to ensure that the application can interact with the clipboard.

  1. Add the Paste Control to the Interface Add the paste control to the user interface layout of the application. The paste control usually appears in the form of a button, consisting of an icon, text, and a background. At least one of the icon and text is required, and the background is mandatory. For example:
@Entry
@Component
struct Index {
  @State message: string = '';
  build() {
    Row() {
      Column({ space: 10 }) {
        TextInput({ placeholder: 'Please enter the verification code', text: this.message })
        PasteButton()
      .padding({ top: 12, bottom: 12, left: 24, right: 24 })
        // Add click event handling logic later
      }
  .width('100%')
    }
.height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

In the above code, we have added the paste control to a layout containing an input box, preparing for reading the clipboard data and filling it into the input box later.

  1. Handle the Click Event of the Paste Control When the user clicks the paste control, the application needs to handle the corresponding click event to obtain and process the data in the clipboard. For example:
.onClick((event: ClickEvent, result: PasteButtonOnClickResult) => {
  if (PasteButtonOnClickResult.SUCCESS === result) {
    pasteboard.getSystemPasteboard().getData((err: BusinessError, pasteData: pasteboard.PasteData) => {
      if (err) {
        console.error(`Failed to get paste data. Code is ${err.code}, message is ${err.message}`);
        return;
      }
      // Set the clipboard content as the text of the input box
      this.message = pasteData.getPrimaryText();
    });
  }
})
Enter fullscreen mode Exit fullscreen mode

In the click event handling function, the clipboard data is obtained through the method pasteboard.getSystemPasteboard().getData(). If the acquisition is successful, the primary text content in the data is set as the text of the input box, realizing the quick paste function.

(III) Display of Paste Control Usage Limitations and Development Steps in a Table

Usage Limitations Development Steps
The temporary authorization will last until the screen is turned off, the application is switched to the background, or the application exits.
There is no limit on the number of calls by the application during the authorization period.
To protect user privacy, the application needs to ensure that the security control is visible and recognizable by the user, avoiding authorization failure due to control style issues.
1. Import clipboard dependencies.
2. Add an input box and the paste control to the interface.
3. Handle the click event of the paste control, obtain and process the clipboard data.

(IV) Example Code: Reading Verification Codes Using the Paste Control

The following is a complete example code of reading verification codes using the paste control:

import { pasteboard, BusinessError } from '@kit.BasicServicesKit';
import { Component, State, ClickEvent, PasteButtonOnClickResult } from '@ohos.arkui.extension.component';
@Entry
@Component
struct Index {
  @State message: string = '';
  build() {
    Row() {
      Column({ space: 10 }) {
        TextInput({ placeholder: 'Please enter the verification code', text: this.message })
        PasteButton()
      .padding({ top: 12, bottom: 12, left: 24, right: 24 })
      .onClick((event: ClickEvent, result: PasteButtonOnClickResult) => {
            if (PasteButtonOnClickResult.SUCCESS === result) {
              pasteboard.getSystemPasteboard().getData((err: BusinessError, pasteData: pasteboard.PasteData) => {
                if (err) {
                  console.error(`Failed to get paste data. Code is ${err.code}, message is ${err.message}`);
                  return;
                }
                this.message = pasteData.getPrimaryText();
              });
            }
          })
      }
  .width('100%')
    }
.height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, when the user clicks the paste control beside the input box for entering the verification code, the application will read the data in the clipboard and fill it into the input box, facilitating the user to quickly enter the verification code.

II. Save Control: Conveniently Saving Files to the Media Library

(I) The Function of the Save Control

The save control provides applications with a fast and convenient way to save files to the media library. Compared with traditional saving methods, it does not require the user to manually select the saving path but directly saves the file to the specified media library path, greatly improving the operation efficiency. Whether it is saving pictures, videos, or other types of files, the save control can quickly complete the saving operation after the user clicks, while ensuring the security of the operation and the reasonable control of permissions.

(II) The Method of Saving Files to the Media Library Using the Save Control

  1. Import Related Dependencies Before using the save control, it is necessary to import the dependency modules related to file operations and media library access. For example:
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
Enter fullscreen mode Exit fullscreen mode

These dependency modules provide the necessary functions for accessing the media library and performing file read and write operations.

  1. Set the File Resources to be Saved and Add the Save Control First, determine the file resources to be saved and add the save control to the application interface. For example, the following code shows how to add the save control to an interface containing a picture:
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
  build() {
    Row() {
      Column({ space: 10 }) {
        // Assume there is a picture resource here. In actual applications, it should be replaced with a real picture resource.
        Image($r('app.media.startIcon'))
      .height(400)
      .width('100%')
        SaveButton()
      .padding({ top: 12, bottom: 12, left: 24, right: 24 })
        // Add click event handling logic later
      }
  .width('100%')
    }
.height('100%')
.backgroundColor(0xF1F3F5)
  }
}
Enter fullscreen mode Exit fullscreen mode

In the above code, we have added the save control to the interface displaying the picture so that the user can conveniently save the picture to the media library after viewing it.

  1. Handle the Click Event of the Save Control When the user clicks the save control, the application needs to handle the click event and execute the operation of saving the file to the media library. For example:
.onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
  if (result === SaveButtonOnClickResult.SUCCESS) {
    const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
    let helper = photoAccessHelper.getPhotoAccessHelper(context);
    try {
      // Create a picture file. Here, the default picture type and format are used. In actual applications, it can be adjusted according to requirements.
      let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
      // Open the file, preparing to write content.
      let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
      // Assume there is a picture resource here. In actual applications, it should be replaced with a real picture resource.
      context.resourceManager.getMediaContent($r('app.media.startIcon').id, 0)
    .then(async value => {
          let media = value.buffer;
          // Write the picture data to the media library file.
          await fileIo.write(file.fd, media);
          await fileIo.close(file.fd);
          promptAction.showToast({ message: 'Saved to the album!' });
        });
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
    }
  } else {
    promptAction.showToast({ message: 'Permission setting failed!' });
  }
})
Enter fullscreen mode Exit fullscreen mode

In the click event handling function, first obtain the application context, then create the resource path (uri) of the picture file through photoAccessHelper, and then use fileIo to open the file and write the picture data. If the saving is successful, a prompt message is displayed to inform the user that the file has been saved to the album; if the saving fails, the corresponding error message is displayed.

(III) Display of Save Control Usage Limitations and Development Steps in a Table

Usage Limitations Development Steps
When the user clicks the save control for the first time, the system will pop up a window to request the user's authorization. If the user clicks "Cancel", clicking again will pop up the window again; if the user clicks "Allow", the application will be granted temporary saving permission, and no window will pop up when clicking again.
The time interval from when the onClick() callback is triggered to when the media library privileged interface is called by the application cannot be greater than 10 seconds.
The user can only obtain one authorization call by clicking the control once.
To protect user privacy, the application needs to ensure that the security control is visible and recognizable by the user, avoiding authorization failure due to control style issues.
1. Import file and media library dependencies.
2. Set the picture resource (or other file resource), and add the save control.
3. Handle the click event of the save control, execute the operation of saving the file to the media library.

(IV) Example Code: Saving Photos Using the Save Control

The following is a complete example code of saving photos using the save control:

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
  build() {
    Row() {
      Column({ space: 10 }) {
        // Assume there is a picture resource here. In actual applications, it should be replaced with a real picture resource.
        Image($r('app.media.startIcon'))
      .height(400)
      .width('100%')
        SaveButton()
      .padding({ top: 12, bottom: 12, left: 24, right: 24 })
      .onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
            if (result === SaveButtonOnClickResult.SUCCESS) {
              const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
              let helper = photoAccessHelper.getPhotoAccessHelper(context);
              try:
                // Create a picture file. Here, the default picture type and format are used. In actual applications, it can be adjusted according to requirements.
                let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
                // Open the file, preparing to write content.
                let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
                // Assume there is a picture resource here. In actual applications, it should be replaced with a real picture resource.
                context.resourceManager.getMediaContent($r('app.media.startIcon').id, 0)
              .then(async value => {
                    let media = value.buffer;
                    // Write the picture data to the media library file.
                    await fileIo.write(file.fd, media);
                    await fileIo.close(file.fd);
                    promptAction.showToast({ message: 'Saved to the album!' });
                  });
              } catch (error) {
                const err: BusinessError = error as BusinessError;
                console.error(`Failed to save photo.
Enter fullscreen mode Exit fullscreen mode

There is a certain amount of profit in the business operation of the enterprise, and in order to achieve sustainable development, it is necessary to consider how to allocate the profit. The following is a simple introduction to several common profit allocation methods:

1. Dividend Distribution

Dividend distribution is a common way for enterprises to allocate profits. It means that the enterprise distributes a certain amount of profits to shareholders in the form of cash or additional shares according to the proportion of their shareholdings. This method can directly return profits to shareholders, allowing them to enjoy the fruits of the enterprise's development. For example, if an enterprise decides to distribute a total dividend of $1 million this year, and a shareholder holds 10% of the shares, then this shareholder will receive a dividend of $100,000.

2. Retained Earnings

Retained earnings refer to the part of the enterprise's net profit that is not distributed as dividends but is retained within the enterprise for future development. This part of the funds can be used for various purposes such as expanding production, investing in new projects, and improving corporate facilities. For example, if an enterprise has a net profit of $5 million this year and decides to retain 40% of it, then the amount of retained earnings will be $2 million. These retained earnings will be used to support the enterprise's growth and expansion in the future.

3. Employee Bonus

Employee bonus is another way to allocate profits. The enterprise distributes a certain amount of profits to employees in the form of bonuses according to their work performance and contributions. This can effectively motivate employees to work harder and improve their work efficiency. For example, if an enterprise decides to allocate $500,000 as employee bonuses this year, and an employee's work performance is excellent and is considered to be worth 10% of the total bonus pool, then this employee will receive a bonus of $50,000.
In general, different profit allocation methods have different effects on the enterprise and its stakeholders. Enterprises need to consider various factors such as their own development stage, financial situation, and strategic goals when choosing a profit allocation method, so as to achieve the best allocation effect and promote the sustainable development of the enterprise.

Top comments (0)