[Huawei Developers] muraliameakula:
Introduction

Harmony OS is the new operating system introduced by Huawei. Harmony OS is built on a distributed architecture design rather than the conventional OS which runs on the stand alone devices.

The Harmony OS support wide array of devices and works well on Smartphones, tablets, wearables and Smart TV’s and head units.

Lightweight preference Database

Lightweight preference database is a storage mechanism offered for Harmony OS and can be used to store small amount of data/information. Data can be saved in simple key-value pair which will be stored in the device’s memory and enable the faster operation.

In this article, we will create a simple login page for smartwatch to store user’s credential into lightweight preference database.

Requirements

1) DevEco IDE

2) Smartwatch wearable simulator

Development

In order to save and load user’s credential, we need to obtain Preferences instance.

private void initializeLightPreferenceDB() {
DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext() );
String fileName = "MyLightPreferenceDB";
preferences = databaseHelper.getPreferences(fileName);
}

First time when user launches the app, user needs to register. User will enter username and password and click on register to store credential into preference database using put() method.

preferences.putString("username", tfUsername.getText());
preferences.putString("password", tfPassword.getText());
preferences.flushSync();

flushSync() is used to write preference in file synchronously. To write synchronously, we can use flush().

When user enters credential and click on login button, app will fetch or query the credential from lightweight preference using get() method and compare it with entered credential to validate.

String username = preferences.getString("username", "");
String password = preferences.getString("password", "");

If validation fails, error message will be shown.

errorText.setVisibility(Component.VISIBLE);
// Set the TextField style when there is an error.
errorText.setText("Invalid Credential");
ShapeElement errorElement = new ShapeElement(this, ResourceTable.Graphic_background_text_field_error);
TextField textField = (TextField) findComponentById(ResourceTable.Id_name_textField);
textField.setBackground(errorElement);
// Cause the TextField to lose focus.
textField.clearFocus();

Code snippet of MainAblitySlice.java

package com.ritesh.chanchal.preferenecedb.slice;

import com.ritesh.chanchal.preferenecedb.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.window.dialog.ToastDialog;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public class MainAbilitySlice extends AbilitySlice {
private TextField tfUsername;
private TextField tfPassword;
private Button bRegister;
private Button bLogin;
private Text errorText;
private Preferences preferences;

static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");

@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initializeLightPreferenceDB();
tfUsername = (TextField) findComponentById(ResourceTable.Id_name_textField);
tfPassword = (TextField) findComponentById(ResourceTable.Id_password_text_field);
errorText = (Text) findComponentById(ResourceTable.Id_error_tip_text);

tfUsername.setFocusChangedListener((component, isFocused) -> {

if (isFocused) {
// The focus is gained.
errorText.setVisibility(Component.HIDE);

ShapeElement shapeElement = new ShapeElement(this, ResourceTable.Graphic_background_text_field);
TextField textField = (TextField) findComponentById(ResourceTable.Id_name_textField);
textField.setBackground(shapeElement);
}
});

tfPassword.setFocusChangedListener((component, isFocused) -> {

if (isFocused) {
// The focus is gained.
errorText.setVisibility(Component.HIDE);
ShapeElement shapeElement = new ShapeElement(this, ResourceTable.Graphic_background_text_field);
TextField textField = (TextField) findComponentById(ResourceTable.Id_name_textField);
textField.setBackground(shapeElement);
}
});

bRegister = (Button) findComponentById(ResourceTable.Id_register_button);
bLogin = (Button) findComponentById(ResourceTable.Id_signin_button);

bRegister.setClickedListener(component -> {
if(!tfPassword.getText().isEmpty() && !tfUsername.getText().isEmpty()) {

preferences.putString("username", tfUsername.getText());
preferences.putString("password", tfPassword.getText());
preferences.flushSync();

HiLog.debug(LABEL, "Registration Successful");
tfPassword.setText("");
tfUsername.setText("");
} else {
// Text of the error message.
errorText.setVisibility(Component.VISIBLE);
// Set the TextField style when there is an error.
errorText.setText("Field cannot be empty");
ShapeElement errorElement = new ShapeElement(this, ResourceTable.Graphic_background_text_field_error);
TextField textField = (TextField) findComponentById(ResourceTable.Id_name_textField);
textField.setBackground(errorElement);

// Cause the TextField to lose focus.
textField.clearFocus();
}
tfUsername.clearFocus();
tfPassword.clearFocus();
});

bLogin.setClickedListener(component -> {
String username = preferences.getString("username", "");
String password = preferences.getString("password", "");
HiLog.debug(LABEL, username + " , " + password);
if(username.isEmpty() || password.isEmpty()) {
// Text of the error message.
errorText.setVisibility(Component.VISIBLE);
// Set the TextField style when there is an error.
errorText.setText("Please Register First");
ShapeElement errorElement = new ShapeElement(this, ResourceTable.Graphic_background_text_field_error);
TextField textField = (TextField) findComponentById(ResourceTable.Id_name_textField);
textField.setBackground(errorElement);

// Cause the TextField to lose focus.
textField.clearFocus();
}
else {
if(username.equals(tfUsername.getText()) && password.equals(tfPassword.getText())){
HiLog.debug(LABEL, "Login Successful");
new ToastDialog(getApplicationContext()).setText("Login Successful").show();
} else {
errorText.setVisibility(Component.VISIBLE);
// Set the TextField style when there is an error.
errorText.setText("Invalid Credential");
ShapeElement errorElement = new ShapeElement(this, ResourceTable.Graphic_background_text_field_error);
TextField textField = (TextField) findComponentById(ResourceTable.Id_name_textField);
textField.setBackground(errorElement);
// Cause the TextField to lose focus.
textField.clearFocus();
}
}
tfUsername.clearFocus();
tfPassword.clearFocus();

});

}

private void initializeLightPreferenceDB() {
DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext() );
String fileName = "MyLightPreferenceDB";
preferences = databaseHelper.getPreferences(fileName);
}

@Override
public void onActive() {
super.onActive();
}

@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}

ability_main.xml contains UI design.

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:background_element="$graphic:background_ability_main"
ohos:orientation="vertical">

<StackLayout
ohos:top_margin="50vp"
ohos:width="match_parent"
ohos:height="match_content"
ohos:layout_alignment="center">
<TextField
ohos:id="$+id:name_textField"
ohos:width="150vp"
ohos:height="35vp"
ohos:multiple_lines="false"
ohos:left_padding="24vp"
ohos:right_padding="24vp"
ohos:top_padding="8vp"
ohos:bottom_padding="8vp"
ohos:text_size="10fp"
ohos:layout_alignment="center"
ohos:text_alignment="center_vertical"
ohos:background_element="$graphic:background_text_field"
ohos:hint="Enter Username" />

<Text
ohos:visibility="hide"
ohos:id="$+id:error_tip_text"
ohos:width="150vp"
ohos:height="35vp"
ohos:top_padding="8vp"
ohos:bottom_padding="8vp"
ohos:right_margin="24vp"
ohos:text="Incorrect account or password"
ohos:text_size="10fp"
ohos:text_color="red"
ohos:layout_alignment="right"/>
</StackLayout>

<TextField
ohos:top_margin="10vp"
ohos:id="$+id:password_text_field"
ohos:width="150vp"
ohos:height="35vp"
ohos:multiple_lines="false"
ohos:left_padding="24vp"
ohos:right_padding="24vp"
ohos:top_padding="8vp"
ohos:bottom_padding="8vp"
ohos:text_size="10fp"
ohos:layout_alignment="center"
ohos:text_alignment="center_vertical"
ohos:background_element="$graphic:background_text_field"
ohos:hint="Enter password" />

<Button
ohos:top_margin="15vp"
ohos:id="$+id:register_button"
ohos:width="120vp"
ohos:height="25vp"
ohos:background_element="$graphic:background_btn"
ohos:text="Register"
ohos:text_color="#ffffff"
ohos:text_size="10fp"
ohos:layout_alignment="horizontal_center"/>

<Button
ohos:top_margin="15vp"
ohos:id="$+id:signin_button"
ohos:width="120vp"
ohos:height="25vp"
ohos:background_element="$graphic:background_btn"
ohos:text="Log in"
ohos:text_color="#ffffff"
ohos:text_size="10fp"
ohos:layout_alignment="horizontal_center"/>

</DirectionalLayout>

We will use background_ability_main.xml to define background color and shape of DependentLayout in ability_main.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<solid
ohos:color="#192841"/>
</shape>

background_btn.xml is used here to define shape and background color of button.

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<corners
ohos:radius="35"/>
<solid
ohos:color="#7700cf"/>
</shape>

background_text_field.xml is used to define shape and background color of textfield.

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<solid
ohos:color="#192841"/>
</shape>

We have defined style for text field to display error in background_text_field_error.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<corners
ohos:radius="40"/>
<solid
ohos:color="gray"/>
<stroke
ohos:color="#E74C3C"
ohos:width="6"/>
</shape>

Tips and Tricks

1. flush() and flushsync() is used to write data asynchronously and synchronously respectively.

2. To obtain the targetContext and srcContext in the preceding code, call the getApplicationContext() method in the AbilitySlice or Ability class.

Conclusion

This article is focused on Harmony OS lightweight preferences database which is very helpful for storing light weight data. This article explains the integration of preferences into simple login app for smartwatch to store user’s credential.

If you found this tutorial helpful, then help us by SHARING this post. Thank You!

Reference

Harmony Official document

Original Source