在过去很长一段时间,我都非常希望能够将OpenHarmony与HarmonyOS设备进行一个联动,但是碍于一些底层接口未完善一直无法实现。但是在前几个月,OpenHarmony3.1 带来了更多可能。本次,我将分享如何在搭载HarmonyOS的手机和搭载OpenHarmony的开发板上,实现socket对话!
0. 效果演示
1.HarmonyOS侧
1.1 新建一个JAVA工程,编写简单的测试页面
- ability_main.xml (主页面)
这是我自己编写的一个测试页面,但不是最重要的。
1.2 编写socket功能
目前,鸿蒙的Socket通信功能只能在JAVA侧实现,并且官网对相关的功能解析不够全面,但是足够实现UDP通信。
这里直接参考官网,可以快速实现Socket功能,传送门:JAVA-socket
在MainAbilitySlice中编写两个主要函数,并结合个人情况绑定到测试按键上即可。
- StartServer()
HiLog.info(LABEL_LOG, "StartServer run"); NetManager netManager = NetManager.getInstance(null); if (!netManager.hasDefaultNet()) { HiLog.error(LABEL_LOG, "netManager.hasDefaultNet() failed"); return; } NetHandle netHandle = netManager.getDefaultNet(); DatagramSocket socket = null; // 通过Socket绑定来进行数据传输 try { HiLog.info(LABEL_LOG, "wait receive data"); //通过getLocalIpAddress()快速获取本机的IP地址 InetAddress address = netHandle.getByName(getLocalIpAddress()); //端口号+主机地址 socket = new DatagramSocket(10006, address); netHandle.bindSocket(socket); /*至此绑定Socket结束*/ HiLog.info(LABEL_LOG, "绑定成功"); /*监听函数*/ byte[] buffer = new byte[1024]; DatagramPacket response = new DatagramPacket(buffer, buffer.length); while (true) { //接收数据 socket.receive(response); int len = response.getLength(); HiLog.info(LABEL_LOG, "接收成功"); //将数据打印到屏幕上 s = new String(buffer, StandardCharsets.UTF_8).substring(0, len); //一个textfield组件 text.setText(s); HiLog.info(LABEL_LOG, "receive data: " + s); } } catch (IOException e) { HiLog.error(LABEL_LOG, "rev IOException: "); } }
- sendMessage()
NetManager netManager = NetManager.getInstance(null); if (!netManager.hasDefaultNet()) { HiLog.error(LABEL_LOG, "netManager.hasDefaultNet() failed"); return; } NetHandle netHandle = netManager.getDefaultNet(); // 通过Socket绑定来进行数据传输 DatagramSocket socket = null; try { //从textfield组件获取用户输入的对端ip地址 HOST = iptf.getText(); InetAddress address = netHandle.getByName(HOST); socket = new DatagramSocket(); netHandle.bindSocket(socket); /*至此 已绑定对端Socket*/ //从一个textfield组件获取用户输入的要发送的信息。 String data = new String(sendtf.getText()); //这里默认还是发送至对端的10006端口 DatagramPacket request = new DatagramPacket(data.getBytes( StandardCharsets.UTF_8), data.length(), address, PORT); // buffer赋值 // 发送数据 socket.send(request); HiLog.info(LABEL_LOG, "send data: " + data); } catch (IOException e) { HiLog.error(LABEL_LOG, "send IOException: "); } finally { if (null != socket) { } }
- getlocalip()
private String getLocalIpAddress() { WifiDevice wifiDevice = WifiDevice.getInstance(getContext()); Optional
ipInfo = wifiDevice.getIpInfo(); int ip = ipInfo.get().getIpAddress(); return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + (ip >> 24 & 0xFF); } 至此,接收信息和发送信息的函数都编写完了。但并没有结束,这样的函数并不能跑在UI线程上,我们必须让其在其他线程上运作,那必须请出我们最爱的EventRunner.
1.3 编写Mythread类
EventRunner传送门
package com.example.hoop.util; import ohos.eventhandler.EventHandler; import ohos.eventhandler.EventRunner; public class Mythread { public static void inUI(Runnable runnable) { //返回主线程 EventRunner runner = EventRunner.getMainEventRunner(); EventHandler eventHandler = new EventHandler(runner); eventHandler.postSyncTask(runnable); } public static void inBG(Runnable runnable) { EventRunner runner = EventRunner.create(true); EventHandler eventHandler = new EventHandler(runner); //投递任务,我们的Socket函数应该投递于此。 eventHandler.postTask(runnable, 0, EventHandler.Priority.IMMEDIATE); } }
- 将任务投递给EventRunner
只需要将刚刚的两个主要函数投递就行了
private void sendMessage() { Mythread.inBG(new Runnable() { @Override public void run() { NetManager netManager = NetManager.getInstance(null); if (!netManager.hasDefaultNet()) { HiLog.error(LABEL_LOG,"netManager.hasDefaultNet() failed"); return; } NetHandle netHandle = netManager.getDefaultNet(); // 通过Socket绑定来进行数据传输 DatagramSocket socket = null; try { //从textfield组件获取用户输入的对端ip地址 HOST=iptf.getText(); InetAddress address = netHandle.getByName(HOST); socket = new DatagramSocket(); netHandle.bindSocket(socket); /*至此 已绑定对端Socket*/ //从一个textfield组件获取用户输入的要发送的信息。 String data = new String(sendtf.getText()); //这里默认还是发送至对端的10006端口 DatagramPacket request = new DatagramPacket(data.getBytes(StandardCharsets.UTF_8), data.length(), address, PORT); // buffer赋值 // 发送数据 socket.send(request); HiLog.info(LABEL_LOG,"send data: " + data); } catch (IOException e) { HiLog.error(LABEL_LOG,"send IOException: "); } finally { if (null != socket) { } } } }); } private void StartServer() { Mythread.inBG(new Runnable() { @Override public void run() { HiLog.info(LABEL_LOG,"StartServer run"); NetManager netManager = NetManager.getInstance(null); if (!netManager.hasDefaultNet()) { HiLog.error(LABEL_LOG,"netManager.hasDefaultNet() failed"); return; } NetHandle netHandle = netManager.getDefaultNet(); DatagramSocket socket = null; // 通过Socket绑定来进行数据传输 try { HiLog.info(LABEL_LOG,"wait receive data"); //通过getLocalIpAddress()快速获取本机的IP地址 InetAddress address = netHandle.getByName(getLocalIpAddress()); //端口号+主机地址 socket = new DatagramSocket(10006, address); netHandle.bindSocket(socket); /*至此绑定Socket结束*/ HiLog.info(LABEL_LOG,"绑定成功"); /*监听函数*/ byte[] buffer = new byte[1024]; DatagramPacket response = new DatagramPacket(buffer, buffer.length); while(true){ //接收数据 socket.receive(response); int len = response.getLength(); HiLog.info(LABEL_LOG,"接收成功"); //将数据打印到屏幕上 s = new String(buffer, StandardCharsets.UTF_8).substring(0, len); Mythread.inUI(new Runnable() { @Override public void run() { //一个textfield组件 text.setText(s); } }); HiLog.info(LABEL_LOG,"receive data: " + s); } } catch (IOException e) { HiLog.error(LABEL_LOG,"rev IOException: " ); } } }); }
2.OpenHarmony侧
2.1 新建工程,编写测试页面
- index.hml
{{ title }} 本机IP{{getIpAddress()}} 2.2 编写Socket功能
OpenHarmony-Socket
import socket from '@ohos.net.socket'; import wifi from '@ohos.wifi'; export default { data: { title: "等待新的消息...", tcp: socket.constructTCPSocketInstance(), remoteip:'none', localip:'none', msg:"A NEW WORLD", udp:socket.constructUDPSocketInstance(), }, onInit() { this.getIpAddress(); this.creatScoket(); this.title="暂无新消息" }, //创建udpSocket 默认端口10006 creatScoket: async function(){ this.udp.bind({address: this.getIpAddress(), port: 10006, family: 1}, err => { if (err) { console.info('bind fail'); this.title='bind fail' return; } this.title='bind success'; console.info('bind success'); }) // this.tcp.bind({address: this.localip, port: 10006,family: 1}, err => { // if (err) { // console.log('bind fail'); // this.title='bind fail'; // return; // } // this.title='bind success'; // console.log('bind success'); // }) //监听收到的信息 打印到屏幕上 this.udp.on('message', value => { let buffer = value.message; let dataView = new DataView(buffer); let str = ""; for (let i = 0;i < dataView.byteLength; ++i) { str += String.fromCharCode(dataView.getUint8(i)) } this.title =str; }); }, sendMessage: async function(){ // let promise1 = this.udp.connect({ address: {address: this.remoteip, port: 10006, family: 1} , timeout: 6000}); // promise1.then(() => { // console.log('connect success'); // let promise2 =this.udp.send({ // data:this.msg // }); // promise2.then(() => { // console.log('send success'); // }).catch(err => { // console.log('send fail'); // }); // }).catch(err => { // this.title='connect fail'; // console.log('connect fail'); // }); //发送信息 let promise = this.udp.send({ data:this.msg, address: { address:this.remoteip, port:10006, family:1 } }); promise.then(() => { this.title='send success'; console.info('send success'); }).catch(err => { this.title='send fail' console.info('send fail'); }); }, newlocalip(e){ this.localip = e.value; this.title = e.value; }, newremoteip(e){ this.remoteip = e.value; }, newMessage(e){ this.msg=e.value; this.title=e.value; }, //获取本机ip地址 getIpAddress(){ let ip=wifi.getIpInfo().ipAddress; this.localip = (ip >> 24 & 0xFF)+"."+ ((ip >> 16) & 0xFF)+"."+((ip >> 8) & 0xFF)+"."+(ip & 0xFF); }, }
3.测试
这里为了便于测试,我们最好下载一个网络调试助手
网络调试助手
3.1结果
- OpenHarmony侧
- HarmonyOS侧
- OpenHarmony&HarmonyOS 联动
4 结语
实现了OpenHarmony与HarmonyOS的简单通讯后,应用开发,软硬件联动都有了更多的可能性。目前可能存在一些稳定性,不完整性问题,未来两侧基础功能不断完善之后,将会变得更有趣也更好用。如有明显错误,希望读者能够积极提出,我会尽力完善。
- index.hml
- 将任务投递给EventRunner
- getlocalip()
- sendMessage()
- StartServer()
猜你喜欢
网友评论
- 搜索
- 最新文章
- 热门文章