牙叔教程 简单易学
使用场景
socketIO
socketIO
SocketIO是在客户端和服务端之间建立的双向通信数据交换技术,在即时通讯、通知与消息推送,实时分析等场景中有较为广泛的应用。
效果展示
autojs版本
8.7.7-0
代码简介
通信是双向的, 所以既有客户端, 也有服务端
1. 服务端
使用koa框架搭建, 使用的主要模块是 "socket.io": "^4.0.1"
2. 客户端
socketIO模块依赖 implementation('io.socket:socket.io-client:2.0.0')
用android studio调试成功以后, 转成dex供给autojs使用
get知识点
- koa搭建socketIO
- autojs使用socketIO
- listView的item_bind, 添加控件监听事件
- 常见的socketIO使用方法
- 多用户的管理
- 多用户的消息传递
- 添加新用户, listView自动滚动到最底部, 让新添加的用户进入视野
- 随机颜色
- 获取用户对应的socket连接
- 用户进入房间, 用户离开房间
- 用户上线, 用户下线
- 格式化时间
- 调用java的字符串格式化
- 随机字符串
- nodemon的使用
代码讲解
服务端
1. 主脚本
io.on("connection", (socket) => { console.log("已连接" + socket.id); socket.on("userLogin", (userName) => { ... }); socket.on("disconnect", function () { ... }); socket.on("deleteUser", function (userName) { ... }); socket.on("joinRoom", function (userName, roomName) { ... }); socket.on("leaveRoom", function (userName) { ... }); socket.on("chat", function (chatContent) { ... }); });
2. nodemon启动服务, 这样代码修改了不用自己再重启了
"dev": "nodemon index.js -i README.md" npm run dev
客户端
1. 导入socketio依赖
let dexPath = "./classes_merge.dex"; log(dexPath); runtime.loadDex(dexPath);
2. 导入需要使用的类
importClass(Packages.io.socket.client.IO); importClass(Packages.io.socket.client.Socket); importClass(Packages.io.socket.emitter.Emitter); importClass(Packages.io.socket.engineio.client.transports.Polling); importClass(Packages.io.socket.engineio.client.transports.WebSocket);
3. UI, 一共四个页面
●配置页面, 用于增加删除用户
●大厅页面, 用户上线离线日志
●房间1号日志页面. 1号房间的用户出入记录, 以及发言记录
●2号, 3号 与1号用途类似
<vertical> <button id="回到配置页"> 回到配置页 </button> <viewpager id="viewpager"> <vertical> 增删用户页面 </vertical> <vertical padding="8"> 大厅日志页面 </vertical> <vertical padding="8"> 房间1号日志页面 </vertical> <vertical padding="8"> 房间2号日志页面 </vertical> <vertical padding="8"> 房间3号日志页面 </vertical> </viewpager> </vertical>
4. 初始化用户数据
let userList = yashuUtil.getUserList(); ui.userList.setDataSource(userList);
5. 更新日志
由于更新日志的方法类似, 都是更新textView的内容, 只是viewId不一样, 所以要方法复用
function 更新日志(日志viewId, data) { let oldContent = ui[日志viewId].text(); let newContent = oldContent + "\n" + data + yashuUtil.getTime(); ui.run(function () { ui[日志viewId].setText(newContent); }); }
6. 用户点击单选按钮, 来选择进入那个房间
itemView.房间列表.setOnCheckedChangeListener(function (radioGroup, id) { let item = itemHolder.item; let viewId = radioGroup.getCheckedRadioButtonId(); if (viewId !== -1) { let radioView = ui.findView(viewId); let value = radioView.getText().toString(); if (radioView.checked) { let roomName = value; item.socket.emit("joinRoom", item.name, roomName); } } });
7. 离开房间
itemView.leave.click(function () { itemView.房间列表.clearCheck(); let item = itemHolder.item; item.socket.emit("leaveRoom", item.name); });
8. 用户发言
itemView.send.click(function () { if (itemView.chatContent.text().length < 1) { log("聊天内容为空"); return false; } let item = itemHolder.item; let user = yashuUtil.getCurrentUser(item.socket); if (user) { if (user.roomName) { item.socket.emit("chat", itemView.chatContent.text() + " "); } else { log("用户没有加入房间"); } } else { log("没找到用户"); } });
9. socket连接时, 注册监听事件
mSocket = IO.socket(baseUrl); mSocket.on(Socket.EVENT_CONNECT, onConnect); mSocket.on("disconnect", onDisconnect); mSocket.on("userLogin", onUserLogin); mSocket.on("userExit", onUserExit); mSocket.on("joinedRoom", onJoinedRoom); mSocket.on("leftRoom", onLeftRoom); mSocket.on("chat", onChat); mSocket.connect();
10. 退出时, 释放资源
events.on("exit", function () { yashuUtil.deleteAllUser(); });
参考文章
声明
部分内容来自网络