[Huawei Developers] HMS Community:
Introduction

In this article, we can learn that how to enter the data in Huawei CloudDB. Suppose, if user wants to insert, update, delete and query their data in safe mode, then the Huawei Cloud databases provides trusted platform for any business level. To do operations in clouddb, user must be authorized by Huawei Authentication Modes, such as Mobile Number, Email address, Huawei ID etc of Auth Service. Auth Service provides an SDK and backend services, supports multiple authentication modes, and provides a powerful management console, enabling you to easily develop and manage user authentication.

If you are new to this application, follow my previous articles:

Beginner: Integration of Huawei Account Kit of Obtaining Icon Resources feature in Attendance Tracker Android app (Kotlin) - Part 1

Beginner: Find Log in via SMS and Forgot password? Features using Huawei Account Kit, and Ads Kit in Attendance Tracker Android app (Kotlin) – Part 2

Beginner: Find the CRUD operations in Room Database in Attendance Tracker Android app (Kotlin) – Part 3

Beginner: Integration of Huawei Crash Service in Attendance Tracker Android app (Kotlin) – Part 4

Beginner: Enter the attendance timings using Room Database and Huawei Analytics Kit in Attendance Tracker Android app (Kotlin) – Part 5

Auth Service

By integrating the Auth Service SDK into your app, you can easily and quickly provide functions such as registration and sign-in for your users. You can choose to provide your users with one or more of the authentication modes.

Cloud DB

Huawei Cloud DB is a device-cloud synergy database product that enables seamless data synchronization between the device and cloud and between devices, and supports offline application operations, helping you quickly develop device-cloud and multi-device synergy applications.

AppGallery Connect

Cloud DB:

1. Choose My Projects > Project Settings > Build > Cloud DB, and click Enable now.

2. Click Add.

3. Enter Object Type Name, Fields and select Data Permissions.

4. Find the updated Fields and selected Data Permissions.

5. Click Export, select Java, android and Package Name, and click OK.

6. Now the ObjectTypeInfoHelper.java and StudentInfo.java model classes will be downloaded, and add it in your Android Project.

Auth Service:

1. Choose My Projects > Project Settings > Build > Auth Service, and enable HUAWEI ID.

2. Enter Client ID and Client Secret details from .json file, and click OK.

Requirements

1. Any operating system (MacOS, Linux and Windows).

2. Must have a Huawei phone with HMS 4.0.0.300 or later.

3. Must have a laptop or desktop with Android Studio, Jdk 1.8, SDK platform 26 and Gradle 4.6 and above installed.

4. Minimum API Level 24 is required.

5. Required EMUI 9.0.0 and later version devices.

How to integrate HMS Dependencies

1. First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a Huawei ID.

2. Create a project in android studio, refer Creating an Android Studio Project.

3. Generate a SHA-256 certificate fingerprint.

4. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > Tasks > android, and then click signingReport, as follows.

Note: Project Name depends on the user created name.

5. Create an App in AppGallery Connect.

6. Download the agconnect-services.json file from App information, copy and paste in android Project under app directory, as follows.

7. Enter SHA-256 certificate fingerprint and click Save button, as follows.

Note: Above steps from Step 1 to 7 is common for all Huawei Kits.

8. Click Manage APIs tab and enable Auth Service.

9. Add the below maven URL in build.gradle(Project) file under the repositories of buildscript, dependencies and allprojects, refer Add Configuration.

maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.6.0.300'

10. Add the below plugin and dependencies in build.gradle(Module) file.

apply plugin: id 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// Huawei Account Kit
implementation 'com.huawei.hms:hwid:6.3.0.301'
// Cloud DB
implementation 'com.huawei.agconnect:agconnect-cloud-database:1.5.0.300'
// Auth Service
implementation "com.huawei.agconnect:agconnect-auth-huawei:1.6.0.300"
implementation 'com.huawei.agconnect:agconnect-auth:1.5.0.300'

11. Now Sync the gradle.

12. Add the required permission to the AndroidManifest.xml file.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Let us move to development

I have created a project on Android studio with empty activity let us start coding.

In the MainActivity.kt activity to find the business logic for Auth Service.

// Obtain the authorization for the HUAWEI ID
private fun findResources() {
mAuthParam = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
.setAccessToken()
.createParams()
mAuthManager = AccountAuthManager.getService(this@MainActivity, mAuthParam)
startActivityForResult(mAuthManager?.signInIntent, 1002)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1002 ) {
// Auth Service, obtaining an access token after successful authorization
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
val authAccount = authAccountTask.result
Log.i(TAG, "accessToken:" + authAccount.accessToken)
// Auth Service, to generate a credential using the obtained access token
val credential = HwIdAuthProvider.credentialWithToken(authAccount.accessToken)
AGConnectAuth.getInstance().signIn(credential).addOnSuccessListener { it ->

Toast.makeText(this, "Auth success", Toast.LENGTH_LONG).show()
val intent = Intent(this@MainActivity, Home::class.java)
startActivity(intent)
}.addOnFailureListener {
Toast.makeText(this, "Auth failed: ", Toast.LENGTH_LONG).show()
}
}
else {
Toast.makeText(this, "SignIn failed: " + (authAccountTask.exception as ApiException).statusCode, Toast.LENGTH_LONG).show()
}
}
}

In the CloudActivity.kt activity to find the business logic for button clicks.

class CloudActivity : AppCompatActivity() {

val TAG = "HomeScreen"
var mCloudDBZone: CloudDBZone? = null
var openCloudDbBtn: Button? = null
var insertDataBtn: Button? = null
var queryDataBtn: Button? = null
var registerUpdateListenerBtn: Button? = null

private var mSnapshotListeners = OnSnapshotListener<StudentInfo?> { cloudDBZoneSnapshot, e ->
if (e != null) {
Log.w("TAG", "onSnapshot: " + e.message)
return@OnSnapshotListener
}
val snapshotObjects = cloudDBZoneSnapshot.snapshotObjects
val studentInfos: MutableList<StudentInfo?> = ArrayList()
try {
if (snapshotObjects != null) {
while (snapshotObjects.hasNext()) {
val studentInfo: StudentInfo? = snapshotObjects.next() as StudentInfo?
studentInfos.add(studentInfo)
}
if (studentInfos.size > 0) {
runOnUiThread {
Toast.makeText(this,"You have entered some value that is matched to the checked condition", Toast.LENGTH_SHORT).show()
}
}
}
} catch (snapshotException: AGConnectCloudDBException) {
Log.w("TAG", "onSnapshot:(getObject) " + snapshotException.message)
} finally {
cloudDBZoneSnapshot.release()
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_cloud)

openCloudDbBtn = findViewById(R.id.btn_dbopen)
insertDataBtn = findViewById(R.id.btn_dbinsert)
queryDataBtn = findViewById(R.id.btn_dbgetall)
registerUpdateListenerBtn = findViewById(R.id.btn_dbreg)

openCloudDbBtn!!.setOnClickListener(View.OnClickListener { setAGC_DB() })
insertDataBtn!!.setOnClickListener(View.OnClickListener { insertDetails(mCloudDBZone!!) })
queryDataBtn!!.setOnClickListener(View.OnClickListener { queryAllStudents() })
registerUpdateListenerBtn!!.setOnClickListener(View.OnClickListener { startRegisterFragment() })

}

private fun setAGC_DB() {
// val user = AGConnectAuth.getInstance().currentUser
AGConnectCloudDB.initialize(applicationContext)
val mCloudDB = AGConnectCloudDB.getInstance()
try {
mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo())
} catch (e: AGConnectCloudDBException) {
e.printStackTrace()
}
val mConfig = CloudDBZoneConfig("Zone1",
CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC)
mConfig.persistenceEnabled = true
val openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true)
openDBZoneTask.addOnSuccessListener { cloudDBZone ->
Toast.makeText(this,"Cloud DB successfully opened", Toast.LENGTH_SHORT).show()
if (mCloudDBZone == null) {
mCloudDBZone = cloudDBZone
}
}.addOnFailureListener { e -> e.printStackTrace() }
}

private fun queryAllStudents() {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it")
return
}
val queryTask: Task<CloudDBZoneSnapshot<StudentInfo>> = mCloudDBZone!!.executeQuery(
CloudDBZoneQuery.where(StudentInfo::class.java),
CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY)
queryTask.addOnSuccessListener { snapshot -> processQueryResult(snapshot) }
.addOnFailureListener { e -> e.message
}
}

private fun processQueryResult(snapshot: CloudDBZoneSnapshot<StudentInfo>) {
val studentInfoCursor: CloudDBZoneObjectList<StudentInfo> = snapshot.snapshotObjects
val studentInfoList: MutableList<StudentInfo> = ArrayList<StudentInfo>()
try {
while (studentInfoCursor.hasNext()) {
val studentInfo: StudentInfo = studentInfoCursor.next()
studentInfoList.add(studentInfo)
}
val fm = supportFragmentManager
val customDialogFragment: RetrieveDialogFragment = RetrieveDialogFragment
.newInstance1("Database Details", studentInfoList)
customDialogFragment.show(fm, "RetrieveDialogFragment")
} catch (e: AGConnectCloudDBException) {
Log.w(TAG, "processQueryResult: " + e.message)
}
snapshot.release()
}

private fun insertDetails(mCloudDBZone: CloudDBZone) {
val fm = supportFragmentManager
val customDialogFragment: InsertDialogFragment = InsertDialogFragment
.newInstance2("Enter Details", mCloudDBZone)
customDialogFragment.show(fm, "InsertDialogFragment")
}

fun startRegisterFragment() {
val fm = supportFragmentManager
val customDialogFragment = RegisterUpdateListenerFragment
.newInstance("Enter Register Details", mCloudDBZone, this.mSnapshotListeners)
customDialogFragment!!.show(fm, "RegisterUpdateListenerFragment")
}

}

Create a InsertDialogFragment.kt fragment to insert the details into CloudDB.

class InsertDialogFragment : DialogFragment() {
var submitBtn: Button? = null
var nameField: EditText? = null
var ageField: EditText? = null
var idField: EditText? = null
var genderField: EditText? = null

override fun onCreate(savedInstanceState: Bundle?) {
setStyle(STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_NoActionBar_MinWidth)
super.onCreate(savedInstanceState)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_insert_dialog, container)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

submitBtn = view.findViewById(R.id.btn_submit)
nameField = view.findViewById(R.id.edt_stu_name)
idField = view.findViewById(R.id.edt_stu_id)
ageField = view.findViewById(R.id.edt_stu_age)
genderField = view.findViewById(R.id.edt_stu_gender)

submitBtn!!.setOnClickListener(View.OnClickListener {
val studentInfo = StudentInfo()
studentInfo.name = nameField!!.text.toString()
studentInfo.age = Integer.valueOf(ageField!!.text.toString())
studentInfo.studentId = idField!!.text.toString()
studentInfo.gender = genderField!!.text.toString()

val upsertTask: Task<Int> = cloudDBZone!!.executeUpsert(studentInfo)
upsertTask.addOnSuccessListener {
Toast.makeText(activity,"Data inserted successfully", Toast.LENGTH_SHORT).show()
}.addOnFailureListener { e ->
e.printStackTrace()
Toast.makeText(activity, e.message, Toast.LENGTH_SHORT).show()
}
})
dialog!!.window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
}

companion object {
var cloudDBZone: CloudDBZone? = null
fun newInstance2(title: String?, cloudDBZone: CloudDBZone?): InsertDialogFragment {
val frag = InsertDialogFragment()
Companion.cloudDBZone = cloudDBZone
val args = Bundle()
args.putString("title", title)
frag.arguments = args
return frag
}
}
}

Create a RetrieveDialogFragment.kt fragment to find the recycler view logic.

class RetrieveDialogFragment : DialogFragment() {

var recyclerView: RecyclerView? = null
var linearLayoutManager: LinearLayoutManager? = null

override fun onCreate(savedInstanceState: Bundle?) {
setStyle(STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_NoActionBar_MinWidth)
super.onCreate(savedInstanceState)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {

val view: View = inflater.inflate(R.layout.fragment_retrieve_dialog, container)
recyclerView = view.findViewById(R.id.stu_list)
recyclerView!!.setHasFixedSize(true)
linearLayoutManager = LinearLayoutManager(activity)
recyclerView!!.layoutManager = linearLayoutManager
recyclerView!!.itemAnimator = DefaultItemAnimator()
recyclerView!!.adapter = studentListAdapter
return view
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

recyclerView = view.findViewById(R.id.stu_list)
dialog!!.window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
}

companion object {
var studentListAdapter: StudentAdapter? = null
var studentInfos: List<StudentInfo>? = null
fun newInstance1(title: String?, studentInfos: List<StudentInfo>?): RetrieveDialogFragment {
val frag = RetrieveDialogFragment()
Companion.studentInfos = studentInfos
studentListAdapter = StudentAdapter(studentInfos!!)
val args = Bundle()
args.putString("title", title)
frag.arguments = args
return frag
}
}

}

Create a StudentAdapter.kt adapter class to hold the list.

class StudentAdapter(localDataSet: List<StudentInfo>) : RecyclerView.Adapter<StudentAdapter.StuViewHolder>() {

private val localDataSet: List<StudentInfo>

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StuViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.student_list, parent, false)
return StuViewHolder(view)
}

override fun onBindViewHolder(holder: StuViewHolder, position: Int) {
holder.stuName.text = localDataSet[position].name
holder.stuId.text = localDataSet[position].studentId
holder.stuGender.text = localDataSet[position].gender
holder.stuAge.text = "Age : " + String.valueOf(localDataSet[position].age)
}

override fun getItemCount(): Int {
return localDataSet.size
}

class StuViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var stuName: TextView
var stuId: TextView
var stuAge: TextView
var stuGender: TextView
init {
stuName = itemView.findViewById(R.id.stu_name)
stuId = itemView.findViewById(R.id.stu_id)
stuAge = itemView.findViewById(R.id.stu_age)
stuGender = itemView.findViewById(R.id.stu_gen)
}
}

init {
this.localDataSet = localDataSet
}

}

Create a RegisterUpdateListenerFragment.kt fragment to register the fields.

class RegisterUpdateListenerFragment : DialogFragment() {

var mRegister: ListenerHandler? = null
var registerBtn: Button? = null
var activity: Activity? = null
var radioGroup: RadioGroup? = null
var nameEditText: EditText? = null
var ageEditText: EditText? = null
var genderEditText: EditText? = null
var stuIdEditText: EditText? = null

override fun onCreate(savedInstanceState: Bundle?) {
setStyle(STYLE_NO_TITLE, android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen)
super.onCreate(savedInstanceState)
activity = getActivity()
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_register_update_listener, container)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

radioGroup = view.findViewById(R.id.RGroup)
nameEditText = view.findViewById(R.id.name_register)
ageEditText = view.findViewById(R.id.age_register)
stuIdEditText = view.findViewById(R.id.id_register)
genderEditText = view.findViewById(R.id.gender_register)
registerBtn = view.findViewById(R.id.register_btn)
registerBtn!!.setOnClickListener(View.OnClickListener { addSubscription() })
radioGroup!!.setOnCheckedChangeListener(RadioGroup.OnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.name_radio -> {
nameEditText!!.visibility = View.VISIBLE
ageEditText!!.visibility = View.GONE
stuIdEditText!!.visibility = View.GONE
genderEditText!!.visibility = View.GONE
}
R.id.age_radio -> {
nameEditText!!.visibility = View.GONE
ageEditText!!.visibility = View.VISIBLE
stuIdEditText!!.visibility = View.GONE
genderEditText!!.visibility = View.GONE
}
R.id.id_radio -> {
nameEditText!!.visibility = View.GONE
ageEditText!!.visibility = View.GONE
stuIdEditText!!.visibility = View.VISIBLE
genderEditText!!.visibility = View.GONE
}
R.id.gender_radio -> {
nameEditText!!.visibility = View.GONE
ageEditText!!.visibility = View.GONE
stuIdEditText!!.visibility = View.GONE
genderEditText!!.visibility = View.VISIBLE
}
else -> {}
}
})
dialog!!.window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
}

fun addSubscription() {
if (cloudDBZone == null) {
Log.w("TAG", "CloudDBZone is null, try re-open it")
return
}
val checkedConditionName: String
val checkedConditionValue: String
var snapshotQuery: CloudDBZoneQuery<StudentInfo?> =
CloudDBZoneQuery.where(StudentInfo::class.java).equalTo("Age", 10)
when (radioGroup!!.checkedRadioButtonId) {
R.id.name_radio -> {
checkedConditionName = "StudentName"
checkedConditionValue = nameEditText!!.text.toString()
snapshotQuery = CloudDBZoneQuery.where(StudentInfo::class.java)
.equalTo(checkedConditionName, checkedConditionValue)
}
R.id.age_radio -> {
checkedConditionName = "Age"
checkedConditionValue = ageEditText!!.text.toString()
snapshotQuery = CloudDBZoneQuery.where(StudentInfo::class.java)
.equalTo(checkedConditionName, checkedConditionValue.toInt())
}
R.id.gender_radio -> {
checkedConditionName = "Gender"
checkedConditionValue = genderEditText!!.text.toString()
snapshotQuery = CloudDBZoneQuery.where(StudentInfo::class.java)
.equalTo(checkedConditionName, checkedConditionValue)
}
R.id.id_radio -> {
checkedConditionName = "StudentId"
checkedConditionValue = stuIdEditText!!.text.toString()
snapshotQuery = CloudDBZoneQuery.where(StudentInfo::class.java)
.equalTo(checkedConditionName, checkedConditionValue)
}
}
try {
mRegister = cloudDBZone!!.subscribeSnapshot(
snapshotQuery, CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY, mSnapshotListeners!!)
Toast.makeText(getActivity(),"Registered successfully", Toast.LENGTH_SHORT).show()
} catch (e: AGConnectCloudDBException) {
Log.w("TAG", "subscribeSnapshot: " + e.message)
}
}

companion object {
var mSnapshotListeners: OnSnapshotListener<StudentInfo?>? = null
var cloudDBZone: CloudDBZone? = null
fun newInstance(title: String?, cloudDBZone: CloudDBZone?, mSnapshotListeners: OnSnapshotListener<StudentInfo?>): RegisterUpdateListenerFragment? {
val frag = RegisterUpdateListenerFragment()
RegisterUpdateListenerFragment.cloudDBZone = cloudDBZone
RegisterUpdateListenerFragment.mSnapshotListeners = mSnapshotListeners
val args = Bundle()
args.putString("title", title)
frag.arguments = args
return frag
}
}

}

In the activity_cloud.xml we can create the UI screen.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".CloudActivity">

<Button
android:id="@+id/btn_dbopen"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:padding="5dp"
android:textColor="@color/white"
android:textSize="18sp"
android:textAllCaps="false"
android:text="Open CloudDB " />
<Button
android:id="@+id/btn_dbinsert"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:padding="5dp"
android:textColor="@color/white"
android:textSize="18sp"
android:textAllCaps="false"
android:text="Insert" />
<Button
android:id="@+id/btn_dbgetall"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:padding="5dp"
android:textColor="@color/white"
android:textSize="18sp"
android:textAllCaps="false"
android:text="Find List" />
<Button
android:id="@+id/btn_dbreg"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:padding="5dp"
android:textColor="@color/white"
android:textSize="18sp"
android:textAllCaps="false"
android:text="Register " />

</LinearLayout>

In the fragment_insert_dialog.xml we can create the UI screen.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<EditText
android:id="@+id/edt_stu_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter name: "
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/edt_stu_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter ID: "
app:layout_constraintTop_toBottomOf="@id/edt_stu_name" />

<EditText
android:id="@+id/edt_stu_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Age: "
app:layout_constraintTop_toBottomOf="@id/edt_stu_id" />

<EditText
android:id="@+id/edt_stu_gender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Gender: "
app:layout_constraintTop_toBottomOf="@id/edt_stu_age" />

<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:textSize="18sp"
android:text="Submit"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/edt_stu_gender" />

</androidx.constraintlayout.widget.ConstraintLayout>

In the fragment_retrieve_dialog.xml we can create the UI screen for recycler view.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/stu_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
</androidx.recyclerview.widget.RecyclerView>

</LinearLayout>

In the student_list.xml we can create the UI screen for customized items.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/stu_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="10dp"
android:textSize="18sp"
android:text="Name: "
android:textColor="@color/teal_700"
android:textStyle="bold" />
<TextView
android:id="@+id/stu_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginTop="10dp"
android:textStyle="bold"
android:textColor="@color/teal_700"
android:text="Student ID: " />
<TextView
android:id="@+id/stu_gen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginTop="10dp"
android:textStyle="bold"
android:textColor="@color/teal_700"
android:text="Gender: " />
<TextView
android:id="@+id/stu_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginTop="10dp"
android:textStyle="bold"
android:textColor="@color/teal_700"
android:text="Age: " />
</LinearLayout>

</androidx.cardview.widget.CardView>

In the fragment_register_update_listener.xml we can create the UI screen for fields.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RadioGroup
android:id="@+id/RGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="50dp"
app:layout_constraintBottom_toTopOf="@id/text_field"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RadioButton
android:id="@+id/name_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="Name " />
<RadioButton
android:id="@+id/id_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="StuID " />
<RadioButton
android:id="@+id/age_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="Age " />
<RadioButton
android:id="@+id/gender_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="Gender " />
</RadioGroup>

<LinearLayout
android:id="@+id/text_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="visible"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toTopOf="@id/register_btn"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/RGroup">

<EditText
android:id="@+id/name_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Name: "
android:visibility="gone" />
<EditText
android:id="@+id/id_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter ID: "
android:visibility="gone" />
<EditText
android:id="@+id/age_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Age: "
android:visibility="gone" />
<EditText
android:id="@+id/gender_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Gender "
android:visibility="gone" />
</LinearLayout>

<Button
android:id="@+id/register_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Register"
android:textSize="18sp"
android:textAllCaps="false"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_field" />

</androidx.constraintlayout.widget.ConstraintLayout>

Demo

Tips and Tricks

1. Make sure you are already registered as Huawei developer.

2. Set minSDK version to 24 or later, otherwise you will get AndriodManifest merge issue.

3. Make sure you have added the agconnect-services.json file to app folder.

4. Make sure you have added SHA-256 fingerprint without fail.

5. Make sure all the dependencies are added properly.

Conclusion

In this article, we have learned to enter the data in Huawei CloudDB. User can insert, update, delete and query their data in safe mode using Huawei Cloud databases provides trusted platform for any business level. User must be authorized by Huawei Authentication Modes, such as Mobile Number, Email address, Huawei ID etc. of Auth Service.

I hope you have read this article. If you found it is helpful, please provide likes and comments.

Reference

CloudDB – Documentation

CloudDB – Training Video

Auth Service – Documentation

Auth Service – Training Video