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.
In HarmonyOS development, we often encounter scenarios where communication is required between the application side (ArkTS) and the front-end page (HTML). For example, the application needs to obtain user input data from the front-end page, or the front-end page needs to call functions on the application side to obtain device information. So, how can we achieve the "whispers" between the application side and the front-end page?
Message Ports: The "Megaphone" between Applications and Front-End Pages
To enable communication between the application side and the front-end page, we can use message ports (MessagePort). Message ports are a mechanism provided by HTML5 for inter-thread communication, allowing two threads to pass data through messages.
In HarmonyOS development, we can use the createWebMessagePorts()
interface to create message ports. This interface returns an array containing two message ports. We can send one port to the front-end page and keep the other port on the application side.
Sample Code: The "Whispers" between ArkTS and HTML
Below, we will demonstrate how to use message ports for communication between ArkTS and HTML through a sample code.
Application Side Code (ArkTS)
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
ports: webview.WebMessagePort[] = [];
@State sendFromEts: string = 'Send this message from ets to HTML';
@State receivedFromHtml: string = 'Display received message send from HTML';
build() {
Column() {
// Display the content received from HTML
Text(this.receivedFromHtml)
// Send the content of the input box to HTML
TextInput({ placeholder: 'Send this message from ets to HTML' })
.onChange((value: string) => {
this.sendFromEts = value;
})
// This content can be called in the onPageEnd lifecycle.
Button('postMessage')
.onClick(() => {
try {
// 1. Create two message ports.
this.ports = this.controller.createWebMessagePorts();
// 2. Register a callback event on the application-side message port (e.g., port 1).
this.ports[1].onMessageEvent((result: webview.WebMessage) => {
let msg = 'Got msg from HTML:';
if (typeof (result) === 'string') {
console.info(`received string message from html5, string is: ${result}`);
msg = msg + result;
} else if (typeof (result) === 'object') {
if (result instanceof ArrayBuffer) {
console.info(`received arraybuffer from html5, length is: ${result.byteLength}`);
msg = msg + 'length is ' + result.byteLength;
} else {
console.info('not support');
}
} else {
console.info('not support');
}
this.receivedFromHtml = msg;
})
// 3. Send the other message port (e.g., port 0) to the HTML side for the HTML side to save and use.
this.controller.postMessage('__init_port__', [this.ports[0]], '*');
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
// 4. Use the application-side port to send a message to the other port that has been sent to html.
Button('SendDataToHTML')
.onClick(() => {
try {
if (this.ports && this.ports[1]) {
this.ports[1].postMessageEvent(this.sendFromEts);
} else {
console.error(`ports is null, Please initialize first`);
}
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.controller })
}
}
}
Front-End Page Code (HTML)
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebView Message Port Demo</title>
</head>
<body>
<h1>WebView Message Port Demo</h1>
<div>
<input type="button" value="SendToEts" onclick="PostMsgToEts(msgFromJS.value);"/><br/>
<input id="msgFromJS" type="text" value="send this message from HTML to ets"/><br/>
</div>
<p class="output">display received message send from ets</p>
</body>
<script>
var h5Port;
var output = document.querySelector('.output');
window.addEventListener('message', function (event) {
if (event.data === '__init_port__') {
if (event.ports[0]!== null) {
h5Port = event.ports[0]; // 1. Save the port sent from the application side.
h5Port.onmessage = function (event) {
// 2. Receive the message sent from the ets side.
var msg = 'Got message from ets:';
var result = event.data;
if (typeof(result) === 'string') {
console.info(`received string message from html5, string is: ${result}`);
msg = msg + result;
} else if (typeof(result) === 'object') {
if (result instanceof ArrayBuffer) {
console.info(`received arraybuffer from html5, length is: ${result.byteLength}`);
msg = msg + 'length is ' + result.byteLength;
} else {
console.info('not support');
}
} else {
console.info('not support');
}
output.innerHTML = msg;
}
}
}
})
// 3. Use h5Port to send a message to the application side.
function PostMsgToEts(data) {
if (h5Port) {
h5Port.postMessage(data);
} else {
console.error('h5Port is null, Please initialize first');
}
}
</script>
</html>
Message Types: More Than Just Strings
Message ports can transmit various types of data, such as strings, objects, ArrayBuffer, etc. This allows us to flexibly pass different types of data to meet various communication needs.
- Strings: The most common message type, suitable for passing text data.
- Objects: Can pass JSON objects, such as device information, user data, etc.
- ArrayBuffer: Suitable for passing binary data, such as images, audio, etc.
By using message ports, we can easily achieve communication between the application side and the front-end page, making development more flexible and efficient.
Top comments (0)