DEV Community

HarmonyOS
HarmonyOS

Posted on

P2P Communication Between Android and (Sport) Lite Wearable Device - Technical Guide

Read the original article:P2P Communication Between Android and (Sport) Lite Wearable Device - Technical Guide

Problem Description

Establishing reliable peer-to-peer (P2P) communication between Android phone applications and wearable device applications presents several technical challenges. Developers often encounter issues with message delivery, file transfer limitations, connection stability, and proper synchronization between the two platforms. The complexity increases when dealing with different device types (lite wearable vs smart wearable) and ensuring both applications are properly installed and running.

Background Knowledge

Communication Architecture

The P2P communication system uses the HiWear SDK to establish a bidirectional communication channel between phone and wearable applications. This system enables:

  • Message Communication: Short text messages up to 1KB
  • File Transfer: Files up to 100MB (phone to wearable) or 4MB (wearable to phone)
  • Status Checking: Verification of app installation and running status
  • Device Management: Connection monitoring and device pairing

Key Components

  • P2pClient: Core communication object for both platforms
  • Message/Builder: Objects for constructing messages and files
  • Callbacks: Event handlers for success, failure, and progress tracking
  • Receivers: Listeners for incoming messages and files

Prerequisites

  • DEVICE_MANAGER permission on the phone application
  • Both applications must be installed on their respective devices
  • Wearable device must be connected to Huawei Health app
  • Proper signing certificate fingerprint configuration

Troubleshooting Process

Step 1: Verify Device Connection and App Installation

Android Side (Phone):

// Step 2: Obtain the P2P communication object.
P2pClient p2pClient = HiWear.getP2pClient(this);
// Package name of an app on a specific device.
String devicePkgName = "com.*.*";

// Step 3: Obtain the version number of your app on the wearable device.
if (connectedDevice != null && connectedDevice.isConnected()) {
    p2pClient.getAppVersion(connectedDevice, devicePkgName)
        .addOnSuccessListener(new OnSuccessListener<Integer>() {
            @Override
            public void onSuccess(Integer versionCode) {
                // -1: The app has not been installed.
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
            }
        });
}
Enter fullscreen mode Exit fullscreen mode

Wearable Side (JavaScript):

// Step 1: Create a P2P communication object.
var p2pClient = new P2pClient();
var peerPkgName = "com.*.*";

// Step 2: Set the package name of your phone app to be communicated with.
p2pClient.setPeerPkgName(peerPkgName);

// Step 3: Check whether your app has been installed on the phone.
p2pClient.ping({
  onSuccess: function() {
    console.log('ping success.');
  },
  onFailure: function() {
    console.log('ping failed');
  },
  onPingResult: function(resultCode) {
    console.log(resultCode.data + resultCode.code);
  },
});

Enter fullscreen mode Exit fullscreen mode

Step 2: Establish Communication Channel

Android Configuration:

P2pClient p2pClient = HiWear.getP2pClient(this);
p2pClient.setPeerPkgName("com.example.wearableapp");
p2pClient.setPeerFingerPrint("FINGERPRINT");
Enter fullscreen mode Exit fullscreen mode

Wearable Configuration:

var p2pClient = new P2pClient();
p2pClient.setPeerPkgName("com.example.phoneapp");
p2pClient.setPeerFingerPrint("FINGERPRINT");
Enter fullscreen mode Exit fullscreen mode

Step 3: Test Communication with Ping

Android Ping Test:

// Step 2: Obtain the P2P communication object.
P2pClient p2pClient = HiWear.getP2pClient(this);

// Step 3: Set the package name of your wearable app to be communicated with.
String peerPkgName = "com.*.*";
p2pClient.setPeerPkgName(peerPkgName);

// Step 4: Check whether your wearable app is running.
if (connectedDevice != null && connectedDevice.isConnected()) {
    p2pClient.ping(connectedDevice, new PingCallback() {
        @Override
        public void onPingResult(int errCode) {
            // 200: app not installed; 201: installed but not started; 202: started.
        }
    }).addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void successVoid) {
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

Wearable Ping Test:

// Step 1: Create a P2P communication object.
var p2pClient = new P2pClient();
var peerPkgName = "com.*.*";

// Step 2: Set the package name of your phone app to be communicated with.
p2pClient.setPeerPkgName(peerPkgName);

// Step 3: Check whether your app has been installed on the phone.
p2pClient.ping({
  onSuccess: function() {
    console.log('ping success.');
  },
  onFailure: function() {
    console.log('ping failed');
  },
  onPingResult: function(resultCode) {
    console.log(resultCode.data + resultCode.code);
  },
});
Enter fullscreen mode Exit fullscreen mode

Step 4: Implement Message Sending

Android to Wearable:

// Step 2: Send a message.
String messageStr = "Hello, Wear Engine!";
Message.Builder builder = new Message.Builder();
builder.setPayload(messageStr.getBytes(StandardCharsets.UTF_8));
Message sendMessage = builder.build();

// Step 3: Obtain the P2P communication object.
P2pClient p2pClient = HiWear.getP2pClient(this);

// Step 4: Specify the package name of your wearable app.
String peerPkgName = "com.*.*";
p2pClient.setPeerPkgName(peerPkgName);

// Step 5: Specify the signing certificate fingerprint.
String peerFingerPrint = "*******";
p2pClient.setPeerFingerPrint(peerFingerPrint);

// Step 6: Send short messages.
SendCallback sendCallback = new SendCallback() {
    @Override
    public void onSendResult(int resultCode) {
        // 207: success
    }
    @Override
    public void onSendProgress(long progress) {
    }
};
if(connectedDevice != null && connectedDevice.isConnected()){
    p2pClient.send(connectedDevice, sendMessage, sendCallback)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void successVoid) {
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
            }
        });
}
Enter fullscreen mode Exit fullscreen mode

Wearable to Android:

// Step 1: Create a P2P communication object.
var p2pClient = new P2pClient();
var peerPkgName = "com.*.*";
var peerFinger = "67DFB7FD********";

// Step 2: Set the package name.
p2pClient.setPeerPkgName(peerPkgName);

// Step 3: Set fingerprint.
p2pClient.setPeerFingerPrint(peerFinger);

// Step 4: Send a short message.
var builderClient = new Builder();
var messageStr = "Hello, Wear Engine!";
builderClient.setDescription(messageStr);

var sendMessage = new Message();
sendMessage.builder = builderClient;

var sendCallback = {
  onSuccess: function() {},
  onFailure: function() {},
  onSendResult: function(resultCode) {
    console.log(resultCode.data + resultCode.code);
  },
}

if(sendMessage != null){
  p2pClient.send(sendMessage, sendCallback);
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Set Up Message Receivers

Android Receiver:

Receiver receiver = new Receiver() {
    @Override
    public void onReceiveMessage(Message message) {
        if (message.getType() == Message.MESSAGE_TYPE_DATA) {
            // Process messages.
        } else if (message.getType() == Message.MESSAGE_TYPE_FILE) {
            // Process files.
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

Wearable Receiver:

var p2pClient = new P2pClient();
var peerPkgName = "com.*.*";
var peerFinger = "67DFB7FD********";

p2pClient.setPeerPkgName(peerPkgName);
p2pClient.setPeerFingerPrint(peerFinger);

var flash = this;
var receiver = {
  onSuccess: function() {
    flash.receiveMessageOK="Succeeded in receiving the message";
  },
  onFailure: function() {
    flash.receiveMessageOK="Failed to receive the message";
  },
  onReceiveMessage: function (data) {
    if (data && data.isFileType) {
      flash.receiveMessageOK = "file:"+data.name;
    } else {
      flash.receiveMessageOK = "message:"+data;
    }
  },
}
p2pClient.registerReceiver(receiver);

// Step 5: Cancel reception
p2pClient.unregisterReceiver({
    onSuccess:function() {
        console.log = ("Stopped receiving messages"); 
    },
    onFailure:function() {
        console.log = ("Failed to stop receiving messages");
    }
});
Enter fullscreen mode Exit fullscreen mode

Analysis Conclusion

Critical Success Factors

  • Proper Permission Management
  • Certificate Fingerprint Matching
  • Package Name Consistency
  • Connection State Verification
  • Lifecycle Management

Solution

Complete Implementation Template

Wearable App Implementation Example (Android):

public class P2PCommunicationManager {
    private P2pClient p2pClient;
    private Device connectedDeice;
    private static final String PEER_PKG_NAME = "com.example.wearableapp";
    private static final String PEER_FINGERPRINT = "FINGERPRINT";

    public void initializeP2P(Context context) {
        p2pClient = HiWear.getP2pClient(context);
        p2pClient.setPeerPkgName(PEER_PKG_NAME);
        p2pClient.setPeerFingerPrint(PEER_FINGERPRINT);
    }

    public void sendMessage(String message) {
        if (isDeviceReady()) {
            Message.Builder builder = new Message.Builder();
            builder.setPayload(message.getBytes(StandardCharsets.UTF_8));
            Message sendMessage = builder.build();

            p2pClient.send(connectedDevice, sendMessage, new SendCallback() {
                @Override
                public void onSendResult(int resultCode) {
                    handleSendResult(resultCode);
                }

                @Override
                public void onSendProgress(long progress) {
                }
            });
        }
    }

    public void registerMessageReceiver() {
        if (isDeviceReady()) {
            Receiver receiver = new Receiver() {
                @Override
                public void onReceiveMessage(Message message) {
                    processReceivedMessage(message);
                }
            };

            p2pClient.registerReceiver(connectedDevice, receiver);
        }
    }

    private boolean isDeviceReady() {
        return connectedDevice != null && connectedDevice.isConnected();
    }
}
Enter fullscreen mode Exit fullscreen mode

Wearable App Implementation Example (JavaScript):

var p2pClient = new P2pClient();
var messageClient = new Message();
var builderClient = new Builder();

export default {
    data: {
    },
    onInit() {
        p2pClient.setPeerPkgName("com.example.phoneapp");
        p2pClient.setPeerFingerPrint("PEER_FINGERPRINT");
        this.registerMessage()
    },
    onDestroy() {
        this.unregisterMessage();
    },
    registerMessage() {
        var flash = this;
        console.log('Register message button click');
        p2pClient.registerReceiver({
            onSuccess: function () {
                console.log('Message receive success');
            },
            onFailure: function () {
                console.log('Message receive fail');
            },
            onReceiveMessage: function (data) {
                if (data && data.isFileType) {
                    console.log("Receive file name:" + data.name);
                } else {
                    console.log('Received message: ' + data);
                }
            },
        });
    },
    unregisterMessage() {
        p2pClient.unregisterReceiver({
            onSuccess: function () {
                console.log("Stop receiving messages is sent");
            },
        });
    },
    sendMessage() {
        builderClient.setDescription("hello wearEngine");
        messageClient.builder = builderClient;
        p2pClient.send(messageClient, {
            onSuccess: function () {
                console.log("Message sent successfully");
            },
            onFailure: function () {
                console.log("Failed to send message");
            },
            onSendResult: function (resultCode) {
                console.log(resultCode.data + resultCode.code);
            },
            onSendProgress: function (count) {
                console.log(count);
            },
        });

    },
}
Enter fullscreen mode Exit fullscreen mode

Verification Result

Testing Checklist

  • Both apps installed and permissions granted
  • Device connection established
  • Ping test successful
  • Two-way messages working
  • File transfer functional
  • Receivers registered correctly
  • Error handling functional
  • App launch via ping verified

Related Documents or Links

Official Documentation

Development Resources

Troubleshooting References

Written by Emine INAN

Top comments (0)