DEV Community

SameX
SameX

Posted on

HarmonyOS Next Cross-Application and Cross-Device Data Sharing in Practice: From Drag-and-Drop to Synchronization

This article aims to deeply explore the technical details of the Huawei HarmonyOS Next system (up to API 12 as of now), 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.

Overview

In today's multi-terminal device ecosystem, achieving seamless data interaction between applications and devices has become one of the key requirements in modern software development. The Ark Data Management (ArkData) and the Unified Data Management Framework (UDMF) of Huawei HarmonyOS provide a flexible solution for cross-application and cross-device data sharing. This article will demonstrate, through a practical case, how to use standardized data structures to achieve cross-application drag-and-drop and utilize distributed data objects to implement cross-device data synchronization, creating a multi-terminal data sharing experience.

Practical Scenario

We will implement data drag-and-drop between two different HarmonyOS applications, specifically including the data interaction of images and text. Meanwhile, with the help of distributed data objects, we will synchronize the dragged data between different devices to ensure multi-terminal data sharing.

1. Creating and Using Standardized Data Structures to Achieve Cross-Application Drag-and-Drop

HarmonyOS can effectively handle different types of data drag-and-drop and sharing through standardized data structures. First, we need to define the data structures so that they can be understood and correctly processed by multiple applications.

Step One: Define Standardized Data Types

In the utd.json5 file of the project, define the data types that we need to drag and share. Take images and plain text as examples:

{
  "UniformDataTypeDeclarations": [
    {
      "TypeId": "com.example.image",
      "BelongingToTypes": ["general.image"],
      "FilenameExtensions": [".jpg", ".png"],
      "MIMETypes": ["image/jpeg", "image/png"],
      "Description": "Shared image",
      "ReferenceURL": ""
    },
    {
      "TypeId": "com.example.text",
      "BelongingToTypes": ["general.plain-text"],
      "Description": "Shared plain text",
      "ReferenceURL": ""
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Step Two: Drag-and-Drop Image and Text Data

In Application A, implement the drag-and-drop function to encapsulate image and text data into standardized data structures.

import { uniformDataStruct, uniformTypeDescriptor, unifiedDataChannel } from '@kit.ArkData';

let imageDetails: Record<string, string> = {
  'attr1': 'image_attribute_1',
  'attr2': 'image_attribute_2',
};

let image: uniformDataStruct.Image = {
  uniformDataType: 'com.example.image',
  url: 'path/to/image.jpg',
  description: 'This is an example image',
  details: imageDetails,
};

// Create plain text data
let plainTextDetails: Record<string, string> = {
  'attr1': 'text_attribute_1',
  'attr2': 'text_attribute_2',
};

let plainText: uniformDataStruct.PlainText = {
  uniformDataType: 'com.example.text',
  textContent: 'This is a plain text example',
  abstract: 'Text abstract',
  details: plainTextDetails,
};

// Put the data into a unified data object
let unifiedData = new unifiedDataChannel.UnifiedData();
let imageRecord = new unifiedDataChannel.UnifiedRecord(uniformTypeDescriptor.UniformDataType.IMAGE, image);
let plainTextRecord = new unifiedDataChannel.UnifiedRecord(uniformTypeDescriptor.UniformDataType.PLAIN_TEXT, plainText);

unifiedData.addRecord(imageRecord);
unifiedData.addRecord(plainTextRecord);

// Drag the data to the target area
unifiedDataChannel.setDragData(unifiedData);
Enter fullscreen mode Exit fullscreen mode

2. Creation, Synchronization of Distributed Data Objects and Cross-Device Data Sharing

Through distributed data objects, we can easily achieve cross-device data sharing. Each instance of a distributed data object can automatically synchronize data across devices.

Step Three: Create Distributed Data Objects

To achieve cross-device synchronization, we need to create distributed data objects for image and text data. First, create the data object on Device A:

import { distributedDataObject } from '@kit.ArkData';

let sessionId = distributedDataObject.genSessionId();
let dataObject = distributedDataObject.create(this.context, unifiedData);

// Set the sessionId for synchronization
dataObject.setSessionId(sessionId);

// Listen to the synchronization status
dataObject.on('status', (sessionId: string, networkId: string, status: string) => {
  if (status == 'restored') {
    console.log(`Data restored on device: ${networkId}`);
  }
});

// Save the data to other devices
let targetDeviceId = 'device_B_network_id'; // The network ID of the target device
dataObject.save(targetDeviceId);
Enter fullscreen mode Exit fullscreen mode

Step Four: Restore Data on Device B

Receive and restore the synchronized data object on the target Device B:

let receivedDataObject = distributedDataObject.create(this.context, null);

// Set the same sessionId for synchronization
receivedDataObject.setSessionId(sessionId);

// Listen to the changes in synchronized data
receivedDataObject.on('change', (sessionId: string, fields: Array<string>) => {
  fields.forEach((field) => {
    console.log(`Field changed: ${field}, new value: ${receivedDataObject[field]}`);
  });
});
Enter fullscreen mode Exit fullscreen mode

3. Listening to Cross-Device Data Changes and Handling Synchronization Conflicts

When distributed data objects synchronize across devices, data conflicts may occur. HarmonyOS provides mechanisms for data listening and conflict handling to ensure that the synchronized data on different devices remains consistent.

Step Five: Handle Synchronization Conflicts

During the data synchronization process, conflicts can be captured by listening to data changes. The following example shows how to handle conflicts during synchronization:

dataObject.on('change', (sessionId: string, fields: Array<string>) => {
  fields.forEach((field) => {
    console.log(`Data field ${field} has changed on session ${sessionId}`);

    // Resolve conflicts: We can manually handle conflicts according to business logic
    if (field === 'textContent') {
      if (receivedDataObject[field]!== dataObject[field]) {
        console.log(`Conflict detected in ${field}.`);
        // Manually resolve conflict logic, for example, keep the latest value
        dataObject[field] = receivedDataObject[field];
      }
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

Summary

Through the practical case in this article, we have demonstrated how to use standardized data structures to achieve cross-application data drag-and-drop and sharing in HarmonyOS, and use distributed data objects to implement data synchronization between multiple devices. Through this method, developers can easily create a seamless experience of multi-terminal data interaction.

The key steps include:

  1. Define and create standardized data structures to ensure the consistency of cross-application data interaction.
  2. Use distributed data objects to implement multi-device data synchronization, reducing development complexity.
  3. Listen to the changes and conflicts in data synchronization to ensure the consistency of data among multiple devices.

Through these technologies, in our daily development, we can not only enhance the user experience but also significantly reduce the development difficulty of cross-terminal applications and quickly achieve multi-device collaborative interaction in the HarmonyOS ecosystem.

Top comments (0)