What Is AppGallery Connect Cloud DB Service

AppGallery Connect (AGC) Cloud DB Service provides collaborative management of device-cloud data, unified data models, and abundant data management APIs. It ensures data availability, reliability, consistency, and security, implements seamless data synchronization between the client and cloud, and provides offline support for applications, helping developers quickly build device-cloud and multi-device collaborative applications.

What Will You Create

In this codelab, you will create an Android app based on the AppGallery Connect Cloud DB, where data can be written and viewed and synchronized between the device and cloud.

What Will You Learn

Development Environment and Skill Requirements

Device Requirements

A device running Android 4.2 or a later version

To integrate the AppGallery Connect Cloud DB service, you need to complete the following preparations:

Enabling the CloudDB Service

Before integrating the Cloud DB SDK, you need to enable the Cloud DB service. The procedure is as follows:

  1. Sign in to AppGallery Connect and click My projects.
  2. Click the project for which you need to enable Cloud DB.
  3. In the navigation tree, choose Build > Cloud DB.
  4. Click Enable now to enable Cloud DB.
  5. Set Data processing location.

Integrating the Cloud DB SDK

If you are using Android Studio, you need to integrate the Cloud DB SDK into your Android Studio project before development.

  1. Sign in to AppGallery Connect and click My projects.
  2. Click your project from the project list.
  3. Go to Project settings > General information. In the App information area, download the agconnect-services.json file.
  4. Copy the agconnect-services.json file to the app directory of the project.
  5. Open the build.gradle file in your app's module directory and add the following code to integrate the Cloud DB SDK:
    dependencies { // Add the Cloud DB SDK. implementation 'com.huawei.agconnect:agconnect-cloud-database:1.5.0.300' }
  1. You can create one data operation layout in the Android Studio project in this codelab.
  2. New functions are as follows:
    • Data query
    • Data writing
  3. You can refer to the following figure to design the UI and develop a book management application.
  4. The sample code for the layout file is as follows:
    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:layout_marginLeft="@dimen/layout_margin" android:layout_marginRight="@dimen/layout_margin"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/field_bookname" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="visible" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/book_name" /> <EditText android:id="@+id/edit_bookname" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="5" android:importantForAutofill="no" android:inputType="text" android:labelFor="@id/edit_bookname" android:maxLength="20" /> </LinearLayout> <LinearLayout android:id="@+id/field_author" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="gone" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/author" /> <EditText android:id="@+id/edit_author" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="5" android:importantForAutofill="no" android:inputType="text" android:labelFor="@id/edit_author" android:maxLength="20" /> </LinearLayout> <LinearLayout android:id="@+id/field_price" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="gone" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/price" /> <EditText android:id="@+id/edit_price" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="5" android:importantForAutofill="no" android:inputType="numberDecimal" android:labelFor="@id/edit_price" android:maxLength="20" /> </LinearLayout> <LinearLayout android:id="@+id/field_search_price" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="gone" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/price" /> <EditText android:id="@+id/lowest_price" android:layout_width="45dp" android:layout_height="wrap_content" android:layout_weight="2.5" android:importantForAutofill="no" android:inputType="numberDecimal" android:labelFor="@id/lowest_price" android:maxLength="20" /> <View android:layout_width="15dp" android:layout_height="2dp" android:layout_gravity="center" android:background="@android:color/black" android:gravity="center" /> <EditText android:id="@+id/highest_price" android:layout_width="45dp" android:layout_height="wrap_content" android:layout_weight="2.5" android:importantForAutofill="no" android:inputType="numberDecimal" android:labelFor="@id/highest_price" android:maxLength="20" /> </LinearLayout> <LinearLayout android:id="@+id/field_publisher" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="gone" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/publisher" /> <EditText android:id="@+id/edit_publisher" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="5" android:importantForAutofill="no" android:inputType="text" android:labelFor="@id/edit_publisher" android:maxLength="20" /> </LinearLayout> <LinearLayout android:id="@+id/field_publish_time" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="gone" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/publish_time" /> <EditText android:id="@+id/edit_publish_time" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="5" android:clickable="false" android:focusable="false" android:focusableInTouchMode="false" android:importantForAutofill="no" android:labelFor="@id/edit_publish_time" android:maxLength="20" /> </LinearLayout> <LinearLayout android:id="@+id/field_show_count" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:visibility="gone" android:weightSum="7" app:layout_constraintTop_toBottomOf="parent"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="@string/show_count" /> <EditText android:id="@+id/edit_show_count" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="5" android:importantForAutofill="no" android:inputType="phone" android:labelFor="@id/edit_show_count" android:maxLength="20" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/layout_margin" android:gravity="center" android:orientation="horizontal"> <Button android:id="@+id/add" style="?android:attr/buttonBarButtonStyle" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="@string/add" /> <Button android:id="@+id/search" style="?android:attr/buttonBarButtonStyle" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="@string/query" /> <Button android:id="@+id/cancel" style="?android:attr/buttonBarButtonStyle" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="@string/cancel" /> </LinearLayout> </RelativeLayout>
  1. Sign in to AppGallery Connect and click My projects.
  2. Select a project from the project list and click an app for which you need to add an object type.
  3. In the navigation tree, choose Build > Cloud DB.
  4. Click Add to go to the object type creation page.
  5. Set Object Type Name to BookInfo, and click Next.
    Click , add the following fields, and click Next.
  6. Field Name

    Type

    Primary Key

    Not Null

    Encryption

    Default Value

    id

    Integer

    bookName

    String

    author

    String

    price

    Double

    publisher

    String

    publishTime

    Date

    shadowFlag

    Boolean

    true

  7. Click , set Index Name to bookName and Index Field to bookName, and click Next.

  8. Set role permissions as follows and click Next.
  9. Role

    query

    upsert

    delete

    Everyone

    Authenticated users

    Data creator

    Administrator

  10. Click OK. The created object types are displayed in the object type list.
  11. Click Export.
  12. Set the format of the file to be exported to JAVA.
  13. Set the Java file type to Android.
  14. Enter the package name com.huawei.agc.clouddb.quickstart.model, that is, the package name in the Java file.
  15. Click Export. The file is exported to the local PC. The file contains all the object type files and object type information files of the version. The exported Java file will be added to the local development environment in subsequent steps.
  1. Sign in to AppGallery Connect and click My projects.
  2. Select a project from the project list and click an app for which you need to add a Cloud DB zone.
  3. In the navigation tree, choose Build > Cloud DB.
  4. Click the Cloud DB Zones tab.
  5. Click Add to go to the Cloud DB zone creation page.
  6. Enter QuickStartDemo in the Cloud DB Zone Name text box.
  7. Click OK.

During application development, you can directly add the JAVA files exported from the AppGallery Connect console to the local development environment, and use the createObjectType() method in the AGConnectCloudDB class to define and create object types. Then you do not need to create object types for local application development.
Add all exported files to the local development environment. If the files exist, replace them. The file is stored in the agc-clouddb-demo-java >/app/src/main/java/com/huawei/agc/clouddb/quickstart/model directory.

After adding the object type file, you can use the Cloud DB for app development. Before developing an application, you need to initialize AGConnectCloudDB and create a Cloud DB zone and object type. The key code for each initialization step is as follows:

  1. Initialize AGConnectCloudDB in the application.
    public static void initAGConnectCloudDB(Context context) { AGConnectCloudDB.initialize(context); }
  2. Obtain an AGConnectCloudDB instance and create an object type.
    public CloudDBZoneWrapper() { mCloudDB = AGConnectCloudDB.getInstance(); } public void createObjectType() { try { mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo()); } catch (AGConnectCloudDBException e) { Log.w(TAG, "createObjectType: " + e.getMessage()); } }
  3. Create a Cloud DB zone configuration object and open the Cloud DB zone.
    public void openCloudDBZoneV2() { mConfig = new CloudDBZoneConfig("QuickStartDemo", CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE, CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC); mConfig.setPersistenceEnabled(true); Task<CloudDBZone> openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true); openDBZoneTask.addOnSuccessListener(new OnSuccessListener<CloudDBZone>() { @Override public void onSuccess(CloudDBZone cloudDBZone) { Log.w(TAG, "open clouddbzone success"); mCloudDBZone = cloudDBZone; // Add subscription after opening cloudDBZone success addSubscription(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Log.w(TAG, "open clouddbzone failed for " + e.getMessage()); } }); }

The following mainly describes how to write data to an application using the Cloud DB SDK. On the application screen, the Add button is added to add data and use executeUpsert() to write data in the CloudDBZoneWrapper. The executeUpsert() method is encapsulated. You can directly use the upsertBookInfos() method to write data. The key code is as follows:

public void upsertBookInfos(BookInfo bookInfo) { if (mCloudDBZone == null) { Log.w(TAG, "CloudDBZone is null, try re-openit"); return; } Task<Integer> upsertTask = mCloudDBZone.executeUpsert(bookInfo); upsertTask.addOnSuccessListener(new OnSuccessListener<Integer>() { @Override public void onSuccess(Integer cloudDBZoneResult) { Log.w(TAG, "upsert " + cloudDBZoneResult + " records"); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { mUiCallBack.updateUiOnError("Insert book info failed"); } }); }

This section describes how to view data in an application, including displaying all data and obtaining updated data.

Displaying All Data

All data is displayed each time you enter the main screen of the application. Call executeQuery(). Set the first parameter to CloudDBZoneQuery.where(BookInfo.class). When the query is successful, execute addOnSuccessListener(). All queried data is transferred through the snapshot parameter. The key code is as follows:

public void queryAllBooks() { if (mCloudDBZone == null) { Log.w(TAG, "CloudDBZone is null, try re-open it"); return; } Task<CloudDBZoneSnapshot<BookInfo>> queryTask = mCloudDBZone.executeQuery( CloudDBZoneQuery.where(BookInfo.class), CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY); queryTask.addOnSuccessListener(new OnSuccessListener<CloudDBZoneSnapshot<BookInfo>>() { @Override public void onSuccess(CloudDBZoneSnapshot<BookInfo> snapshot) { processQueryResult(snapshot); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { mUiCallBack.updateUiOnError("Query book list from cloud failed"); } }); }

Obtaining and Displaying the Updated Data

Data added on the application screen will be synchronized to the cloud. You can add a listener on the device to listen to the objects that meet the conditions. When the object data that meets the conditions changes, the data is pushed to the device. The device can receive the changed object data in the listener callback.
When the application is started, you can use the subscribeSnapshot() method to register the listening of data changes and use the listener mSnapshotListener to obtain data changes in real time.

public void addSubscription() { if (mCloudDBZone == null) { Log.w(TAG, "CloudDBZone is null, try re-open it"); return; } try { CloudDBZoneQuery<BookInfo> snapshotQuery = CloudDBZoneQuery.where(BookInfo.class) .equalTo(BookEditFields.SHADOW_FLAG, true); mRegister = mCloudDBZone.subscribeSnapshot(snapshotQuery, CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY, mSnapshotListener); } catch (AGConnectCloudDBException e) { Log.w(TAG, "subscribeSnapshot: " + e.getMessage()); } }

Obtain the updated data by defining the listener mSnapshotListener. You can use getSnapshotObjects() to obtain the latest data, use next() to traverse specific objects, and use mUiCallBack.onSubscribe(bookInfos) to update the UI.

private OnSnapshotListener<BookInfo> mSnapshotListener = new OnSnapshotListener<BookInfo>() { @Override public void onSnapshot(CloudDBZoneSnapshot<BookInfo> cloudDBZoneSnapshot, AGConnectCloudDBException e) { if (e != null) { Log.w(TAG, "onSnapshot: " + e.getMessage()); return; } CloudDBZoneObjectList<BookInfo> snapshotObjects = cloudDBZoneSnapshot.getSnapshotObjects(); List<BookInfo> bookInfos = new ArrayList<>(); try { if (snapshotObjects != null) { while (snapshotObjects.hasNext()) { BookInfo bookInfo = snapshotObjects.next(); bookInfos.add(bookInfo); updateBookIndex(bookInfo); } } mUiCallBack.onSubscribe(bookInfos); } catch (AGConnectCloudDBException snapshotException) { Log.w(TAG, "onSnapshot:(getObject) " + snapshotException.getMessage()); } finally { cloudDBZoneSnapshot.release(); } } };
  1. Run your Android Studio project and generate an APK. Then, install the APK on your mobile phone for testing.
  2. Open the installed APK package, tap +, and add data on the test phone.

  3. Open Cloud DB, click the Data Entries tab page, and select the corresponding Cloud DB zone and object type. The three new data records are displayed.

Congratulations! You have successfully built your first app that integrates the App Gallery Connect Cloud DB and learned how to add data from the device to the cloud through the App Gallery Connect Cloud DB.

For details about the APIs of AppGallery Connect Cloud DB, see the Cloud DB API Reference.

Sample code

Code copied