- springboot項目結(jié)構(gòu),也可用spring項目,和框架沒有關(guān)系胖眷,沒有影響
H5和H5之間通信
H5和Andorid之間通信
Andorid和Andorid之間通信
H5通過http協(xié)議調(diào)用接口發(fā)送消息-給移動Andorid碳却、H5等
后臺支持語言:java
前端支持語言:Andorid(java)、H5(html)妈拌、jsp等
發(fā)送:發(fā)送給所有連接者、發(fā)送給所有在線者、發(fā)送給指定用戶桦山、及(發(fā)送對象)用戶不在線處理
注:把連接地址改了,可以直接使用復(fù)制代碼測試使用醋旦;
H5和Andorid測試頁面:
Andorid測試頁面 --消息發(fā)送者 發(fā)送指定用戶 【消息接收者1】恒水,也可以發(fā)送所有人 | |
---|---|
Andorid測試頁面.jpg
|
消息接收者1 | 消息接收者2 |
---|---|
測試頁面1.jpg
|
測試頁面2.jpg
|
通過Http發(fā)送測試頁面
發(fā)送消息給所有在線用戶 | 發(fā)送消息給指定在線用戶 --【測試用戶 -張三】 |
---|---|
http測試發(fā)送消息給所有在線用戶.jpg
|
http測試發(fā)送消息給指定在線用戶.jpg
|
測試用戶李四 | 測試用戶張三 |
測試用戶【李四】.jpg
|
測試用戶【張三】.jpg
|
java后臺代碼
引入依賴:
<!--集成移動和H5的java_websocket-->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.0</version>
</dependency>
springboot項目結(jié)構(gòu),也可用spring項目饲齐,和框架沒有關(guān)系钉凌,沒有影響
1.WebSocketPool自定義工具類
主要是連接池,存用戶和WebSocket連接
自定義 WebSocketPool.java
package com.dist.utils;
import org.java_websocket.WebSocket;
import java.util.*;
public class WebSocketPool {
//連接-用戶名
private static final Map<WebSocket, String> userconnections = new HashMap<WebSocket, String>();
/**
* 獲取用戶名
* @param conn
* @return
*/
public static String getUserByKey(WebSocket conn) {
return userconnections.get(conn);
}
/**
* 獲取在線總數(shù)
* @return
*/
public static int getUserCount() {
return userconnections.size();
}
/**
* 獲取WebSocket
* @param user
* @return
*/
public static WebSocket getWebSocketByUser(String user) {
Set<WebSocket> keySet = userconnections.keySet();
synchronized (keySet) {
for (WebSocket conn : keySet) {
String cuser = userconnections.get(conn);
if (cuser.equals(user)) {
return conn;
}
}
}
return null;
}
/**
* 向連接池中添加連接
* @param user
* @param conn
*/
public static void addUser(String user, WebSocket conn) {
userconnections.put(conn, user); // 添加連接
}
/**
* 獲取所有連接池
*/
public static Set<WebSocket> getAllWebSocket() {
return userconnections.keySet();
}
/**
* 移除連接池中的連接
* @param conn
* @return
*/
public static boolean removeUser(WebSocket conn) {
if (userconnections.containsKey(conn)) {
userconnections.remove(conn); // 移除連接
return true;
} else
return false;
}
/**
* 獲取所有的在線用戶
* @return
*/
public static Collection<String> getOnlineUser() {
List<String> setUsers = new ArrayList<String>();
Collection<String> setUser = userconnections.values();
for (String u: setUser) {
setUsers.add(u);
}
return setUsers;
}
/**
* 向特定的用戶發(fā)送數(shù)據(jù)
* @param conn
* @param message
*/
public static void sendMessageToOnlineUser(WebSocket conn, String message) {
if (null != conn) {
conn.send(message);
}
}
/**
* 向所有在線用戶發(fā)送消息
* @param message
*/
public static void sendMessageToOnlineAllUser(String message) {
Set<WebSocket> keySet = userconnections.keySet();
synchronized (keySet) {
for (WebSocket conn : keySet) {
String user = userconnections.get(conn);
if (user != null) { conn.send(message);
}
}
}
}
}
2.創(chuàng)建房間類
為的是開啟房間
ChatServer.java
package com.dist.service;
import com.dist.utils.WebSocketPool;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Set;
/**
* 與不同的客戶端進(jìn)行通訊的思路為:
* Step1:在連接成功的時候捂人,向服務(wù)器發(fā)送自己的用戶名御雕,服務(wù)器做用戶標(biāo)記;
* Step2: 發(fā)送消息滥搭,格式為“XX@XXX”酸纲,@前面表示將要發(fā)送的對象,“all”表示群發(fā)瑟匆,@后面表示發(fā)送的消息闽坡。
*/
public class ChatServer extends WebSocketServer {
private String username;
public ChatServer(int port) throws UnknownHostException {
super(new InetSocketAddress(port));
}
public ChatServer(InetSocketAddress address) {
super(address);
System.out.println("地址:"+address);
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
System.out.println("連接:"+conn);
sendToAll(conn.getRemoteSocketAddress().getAddress().getHostAddress()
+ " 進(jìn)入房間 !");
System.out.println(conn.getRemoteSocketAddress().getAddress()
.getHostAddress()
+ " 進(jìn)入房間 脓诡!");
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
sendToAll(conn.getRemoteSocketAddress().getAddress().getHostAddress()
+ " 離開房間 无午!");
System.out.println(conn.getRemoteSocketAddress().getAddress()
.getHostAddress()
+ " 離開房間 !");
//觸發(fā)關(guān)閉事件
userLeave(conn);
}
//消息發(fā)送
@Override
public void onMessage(WebSocket conn, String message) {
//判斷是否是第一次接收的消息
boolean isfirst = true;
/*sendToAll("["
+ conn.getRemoteSocketAddress().getAddress().getHostAddress()
+ "]" + message);*/
System.out.println("["
+ conn.getRemoteSocketAddress().getAddress().getHostAddress()
+ "]" + message);
//判斷是否已在連接池中
Set<WebSocket> webSockets=WebSocketPool.getAllWebSocket();
for (WebSocket webSocket : webSockets){
if (webSocket.equals(conn)){
isfirst =false;
}
}
if (isfirst) {
this.username = message;
//客戶端發(fā)送消息到服務(wù)器是觸發(fā)事件
if (message != null){
//判斷用戶是否已經(jīng)在線
WebSocket webSocketByUser = WebSocketPool.getWebSocketByUser(message);
if (null == webSocketByUser){
//將用戶加入連接池-在線
this.userJoin(username, conn);
System.out.println("用戶" + username + "上線,在線人數(shù):" + WebSocketPool.getUserCount());
}else {
WebSocketPool.sendMessageToOnlineUser(conn,"["+username+"] 用戶已在線,請您換個用戶登錄祝谚!");
}
}
} else {
String[] msg = message.split("@", 2);//以@為分隔符把字符串分為xxx和xxxxx兩部分,msg[0]表示發(fā)送至的用戶名宪迟,all則表示發(fā)給所有人
if (msg[0].equals("all")) {
sendToAll(msg[1]);
} else {
//指定用戶發(fā)送消息
sendMessageToUser(conn,msg[0], msg[1]);
}
}
}
//異常拋出
@Override
public void onError(WebSocket conn, Exception e) {
e.printStackTrace();
if (conn != null) {
conn.close();
}
}
// 發(fā)送給所有進(jìn)入房間的人
private void sendToAll(String text) {
Collection<WebSocket> conns = connections();
synchronized (conns) {
for (WebSocket client : conns) {
client.send(text);
}
}
}
// 測試
public static void main(String[] args) throws InterruptedException,
IOException {
/*int port = 8887;
ChatServer server = new ChatServer(port);
server.start();
System.out.println("房間已開啟,等待客戶端接入交惯,端口號: " + server.getPort());
BufferedReader webSocketIn = new BufferedReader(new InputStreamReader(
System.in));
while (true) {
String stringIn = webSocketIn.readLine();
// 發(fā)送給所有的聊天者
server.sendToAll(stringIn);
}*/
}
/**
* 用戶下線處理
* @param conn
*/
public void userLeave(org.java_websocket.WebSocket conn) {
String user = WebSocketPool.getUserByKey(conn);
boolean b = WebSocketPool.removeUser(conn); // 在連接池中移除連接
if (b) {
WebSocketPool.sendMessageToOnlineAllUser(user); // 把當(dāng)前用戶從所有在線用戶列表中刪除
String leaveMsg = "[系統(tǒng)]" + user + "下線了";
WebSocketPool.sendMessageToOnlineAllUser(leaveMsg); // 向在線用戶發(fā)送當(dāng)前用戶退出的信息
}
}
/**
* 用戶上線處理
* @param user
* @param conn
*/
public void userJoin(String user, org.java_websocket.WebSocket conn) {
WebSocketPool.sendMessageToOnlineAllUser(user); // 把當(dāng)前用戶加入到所有在線用戶列表中
String joinMsg = "[系統(tǒng)]" + user + "上線了次泽!";
WebSocketPool.sendMessageToOnlineAllUser(joinMsg); // 向所有在線用戶推送當(dāng)前用戶上線的消息
WebSocketPool.addUser(user, conn); // 向連接池添加當(dāng)前的連接的對象
WebSocketPool.sendMessageToOnlineUser(conn, WebSocketPool.getOnlineUser().toString()); // 向當(dāng)前連接發(fā)送當(dāng)前在線用戶的列表
}
/**
* 發(fā)送消息給指定用戶
* @param currentConnection 當(dāng)前連接
* @param user 發(fā)送對象
* @param message 消息
*/
public void sendMessageToUser(WebSocket currentConnection,String user,String message){
WebSocket conn = WebSocketPool.getWebSocketByUser(user); //獲取發(fā)送對象用戶的在線連接
if (null != conn){
//向特定在線用戶發(fā)送消息
WebSocketPool.sendMessageToOnlineUser(conn,message);
//同時發(fā)送消息給當(dāng)前用戶
WebSocketPool.sendMessageToOnlineUser(currentConnection,message);
}else {
WebSocketPool.sendMessageToOnlineUser(currentConnection,"["+user+"] 用戶不在線,請您稍后發(fā)送!");
System.out.println("["+user+"] 用戶不在線,請您稍后發(fā)送席爽!");
WebSocketPool.sendMessageToOnlineUser(currentConnection,"當(dāng)前在線人數(shù):"+WebSocketPool.getUserCount()+" 有:"+WebSocketPool.getOnlineUser());
}
}
}
3.Http發(fā)送消息
在controller層 創(chuàng)建WebSocketController.java
package com.dist.controller;
import com.dist.utils.WebSocketPool;
import org.java_websocket.WebSocket;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author zhengja@dist.com.cn
* @data 2019/4/17 14:54
*/
@RestController
@RequestMapping("/WebSocket")
public class WebSocketController {
//推送給所有在線用戶
@RequestMapping(value = "v1/sendAllUser", method = RequestMethod.GET)
public void sendAllUser(@RequestParam String message){
//推送給所有在線用戶
WebSocketPool.sendMessageToOnlineAllUser(message);
}
//推送給在線的指定用戶
@RequestMapping(value = "v1/sendUser", method = RequestMethod.GET)
public void loginWithDevice(@RequestParam String pushObject,
@RequestParam String message){
//推送的設(shè)備對象
List<String> userlist = null;
if (pushObject == null || "".equals(pushObject)) {
System.out.println("推送對象不能為nuul");
} else {
userlist = new ArrayList<>(Arrays.asList(pushObject.split(",")));
}
for (String user : userlist){
//根據(jù)用戶查找推送的連接對象是否在線
WebSocket webSocketByUser = WebSocketPool.getWebSocketByUser(user);
if (null != webSocketByUser){
//推送給在線的指定用戶
WebSocketPool.sendMessageToOnlineUser(webSocketByUser,message);
}else {
//未推送成功處理模塊
System.out.println("用戶 【"+user+"】 不在線意荤,推送失敗 ! ");
}
}
}
}
4.創(chuàng)建啟動任務(wù)
項目起動后自動啟動這個任務(wù)-開啟房間
TestStarts.java
import com.dist.service.ChatServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class TestStarts implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
int port = 8887;
ChatServer server = new ChatServer(port);
server.start();
System.out.println("項目啟動中:房間已開啟");
System.out.println("等待客戶端接入的端口號: " + server.getPort());
}
}
H5前端代碼:
H5測試頁面:引入jquery.js (放同級目錄)
目前測試頁面上的數(shù)據(jù)信息是寫死的只锻,自己可以重后臺獲取數(shù)據(jù)玖像,寫成動態(tài)的
測試頁面1
H5-WebSocket.html
注意:var wsUri ="ws://129.204.207.127:8887"; 把地址改成自己的服務(wù)器地址,端口不是服務(wù)器的齐饮,是TestStarts.java啟動任務(wù)自定義創(chuàng)建的
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>H5-WebSocket Test</title>
<script src="jquery.js"></script>
</head>
<body>
<br name="#" method="post">
<!--YOUR DATA AREA-->
<label id="a">當(dāng)前用戶</label>
<select id="loginsel">
<option value="2">李四</option>
<option value="3">張三</option>
<option value="4">王二</option>
</select>
<input type="button" value="連接" id="btnconnection" onclick="connectionAction()"/>
<input type="button" value="斷開" id="btndisconnect" onclick="disconnectAction()"/></br></br>
<label id="b">發(fā)送對象</label>
<select id="sel">
<option value="1" selected>all</option>
<option value="2">李四</option>
<option value="3">張三</option>
<option value="4">王二</option>
</select>
<label id="msg">要發(fā)送的信息</label><input type="text" id="message">
<input type="button" id="btnsendMessage" value="發(fā)送消息" onclick="sendMessageAction()">
</form>
<script language="javascript"type="text/javascript">
var wsUri ="ws://129.204.207.127:8887";
var output;
var message;
var userToMessage;
var websocket;
function connectionAction() {
output = document.getElementById("output");
//websocket的房間
websocket = new WebSocket(wsUri);
//打開連接
websocket.onopen = function(evt) {
var loginuser = $('#loginsel option:selected').text();
websocket.send(loginuser);
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
$("#loginsel").attr("disabled","disabled");
$("#btnconnection").attr("disabled","disabled");
$("#btndisconnect").removeAttr("disabled");
$("#sel").removeAttr("disabled");
$("#msg").removeAttr("disabled");
$("#btnsendMessage").removeAttr("disabled");
}
//給指定用戶發(fā)送消息
function sendMessageAction() {
var sendTouser = $('#sel option:selected').text();
message =document.getElementById("message").value;
userToMessage = sendTouser +"@"+message;
websocket.send(userToMessage);
}
//斷開連接
function disconnectAction() {
websocket.close();
writeToScreen("您已斷開連接");
$("#loginsel").removeAttr("disabled");
$("#btnconnection").removeAttr("disabled");
$("#btndisconnect").attr("disabled","disabled");
$("#sel").attr("disabled","disabled");
$("#msg").attr("disabled","disabled");
$("#btnsendMessage").attr("disabled","disabled");
}
/* function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
}*/
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("Zhansna");
}
function onClose(evt) {
writeToScreen("您已斷開連接");
websocket.close();
}
//接收消息
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>');
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>
</body>
</html>
測試頁面2
H5-WebSocket2.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>H5-WebSocket Test2</title>
<script src="jquery.js"></script>
</head>
<body>
<br name="#" method="post">
<!--YOUR DATA AREA-->
<label id="a">當(dāng)前用戶</label>
<select id="loginsel">
<option value="2">李四</option>
<option value="3">張三</option>
<option value="4">王二</option>
</select>
<input type="button" value="連接" id="btnconnection" onclick="connectionAction()"/>
<input type="button" value="斷開" id="btndisconnect" onclick="disconnectAction()"/></br></br>
<label id="b">發(fā)送對象</label>
<select id="sel">
<option value="1" selected>all</option>
<option value="2">李四</option>
<option value="3">張三</option>
<option value="4">王二</option>
</select>
<label id="msg">要發(fā)送的信息</label><input type="text" id="message">
<input type="button" id="btnsendMessage" value="發(fā)送消息" onclick="sendMessageAction()">
</form>
<script language="javascript"type="text/javascript">
var wsUri ="ws://129.204.207.127:8887";
var output;
var message;
var userToMessage;
var websocket;
function connectionAction() {
output = document.getElementById("output");
//websocket的房間
websocket = new WebSocket(wsUri);
//打開連接
websocket.onopen = function(evt) {
var loginuser = $('#loginsel option:selected').text();
websocket.send(loginuser);
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
$("#loginsel").attr("disabled","disabled");
$("#btnconnection").attr("disabled","disabled");
$("#btndisconnect").removeAttr("disabled");
$("#sel").removeAttr("disabled");
$("#msg").removeAttr("disabled");
$("#btnsendMessage").removeAttr("disabled");
}
//給指定用戶發(fā)送消息
function sendMessageAction() {
var sendTouser = $('#sel option:selected').text();
message =document.getElementById("message").value;
userToMessage = sendTouser +"@"+message;
websocket.send(userToMessage);
}
//斷開連接
function disconnectAction() {
websocket.close();
writeToScreen("您已斷開連接");
$("#loginsel").removeAttr("disabled");
$("#btnconnection").removeAttr("disabled");
$("#btndisconnect").attr("disabled","disabled");
$("#sel").attr("disabled","disabled");
$("#msg").attr("disabled","disabled");
$("#btnsendMessage").attr("disabled","disabled");
}
/* function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
}*/
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("Zhansna");
}
function onClose(evt) {
writeToScreen("您已斷開連接");
websocket.close();
}
//接收消息
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>');
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test2</h2>
<div id="output"></div>
</body>
</html>
現(xiàn)在就可以實現(xiàn)H5頁面之間的通信啦
以上只是H5測試用例捐寥,真正用的項目中也是這樣笤昨,只不過,要根據(jù)項目需求該代碼邏輯握恳。我的項目就是版本推送和反饋消息的及時推送瞒窒;
Andorid測試代碼:
測試最好創(chuàng)建空白的Andorid app
在.gradle 引入java-websocket依賴
dependencies{
implementation 'org.java-websocket:Java-WebSocket:1.3.0'
}
頁面代碼
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
>
<ScrollView
android:id="@+id/svChat"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Spinner
android:id="@+id/spDraft"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- ws://192.168.1.104:80/JSR356-WebSocket/websocket/ -->
<!-- ws://192.168.1.104:8887 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/etAddress"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4" />
<Spinner
android:id="@+id/spAddress"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!--選擇登錄用戶-->
<EditText
android:id="@+id/etloginName"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:hint="選著登錄名" /><!--Jack-->
<Spinner
android:id="@+id/sploginName"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
<Button
android:id="@+id/btnConnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="連接" />
<Button
android:id="@+id/btnClose"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="斷開" />
<EditText
android:id="@+id/etDetails"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:focusable="false"
android:focusableInTouchMode="false"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="13dp" />
<Button
android:id="@+id/btnClearDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="清除聊天記錄" />
</LinearLayout>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="@+id/spName"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
<!--<EditText
android:id="@+id/etName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:hint="發(fā)送對象"
android:text=""
android:layout_weight="1"/>--><!--Jack-->
<EditText
android:id="@+id/etMessage"
android:layout_width="0dp"
android:layout_height="match_parent"
android:hint="發(fā)送消息內(nèi)容"
android:layout_weight="4"/>
<Button
android:id="@+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="發(fā)送"/>
</LinearLayout>
</LinearLayout>
邏輯代碼
MainActivity.java
package com.dist.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Spinner;
import org.java_websocket.WebSocketImpl;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_10;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.drafts.Draft_75;
import org.java_websocket.drafts.Draft_76;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ScrollView svChat;
private Spinner spDraft;
private EditText etAddress;
private Spinner spAddress;
private Spinner sploginName;
private EditText etloginName;
private Button btnConnect;
private Button btnClose;
private EditText etDetails;
private Button btnClearDetails;
private Spinner spName;
//private EditText etName;
private EditText etMessage;
private Button btnSend;
private WebSocketClient client;// 連接客戶端
private DraftInfo selectDraft;// 連接協(xié)議
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
svChat = (ScrollView) findViewById(R.id.svChat);
spDraft = (Spinner) findViewById(R.id.spDraft);
etAddress = (EditText) findViewById(R.id.etAddress);
spAddress = (Spinner) findViewById(R.id.spAddress);
sploginName = (Spinner) findViewById(R.id.sploginName);
etloginName = (EditText) findViewById(R.id.etloginName);
btnConnect = (Button) findViewById(R.id.btnConnect);
btnClose = (Button) findViewById(R.id.btnClose);
etDetails = (EditText) findViewById(R.id.etDetails);
btnClearDetails = (Button) findViewById(R.id.btnClearDetails);
spName = (Spinner) findViewById(R.id.spName);
//etName = (EditText) findViewById(R.id.etName);
etMessage = (EditText) findViewById(R.id.etMessage);
btnSend = (Button) findViewById(R.id.btnSend);
DraftInfo[] draftInfos = {new DraftInfo("WebSocket協(xié)議Draft_17", new Draft_17()), new DraftInfo
("WebSocket協(xié)議Draft_10", new Draft_10()), new DraftInfo("WebSocket協(xié)議Draft_76", new Draft_76()), new
DraftInfo("WebSocket協(xié)議Draft_75", new Draft_75())};// 所有連接協(xié)議
selectDraft = draftInfos[0];// 默認(rèn)選擇第一個連接協(xié)議
ArrayAdapter<DraftInfo> draftAdapter = new ArrayAdapter<DraftInfo>(this, android.R.layout
.simple_spinner_item, draftInfos);
spDraft.setAdapter(draftAdapter);
spDraft.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectDraft = (DraftInfo) spDraft.getItemAtPosition(position);// 選擇連接協(xié)議
etDetails.append("當(dāng)前連接協(xié)議:" + selectDraft.draftName + "\n");
Log.e("wlf", "選擇連接協(xié)議:" + selectDraft.draftName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
selectDraft = null;// 清空
Log.e("wlf", "未選擇任何連接協(xié)議");
}
});
ServerInfo[] serverInfos = {new ServerInfo("連接內(nèi)網(wǎng)web后臺", "ws://192.168.2.114:8887"),new ServerInfo("連接外網(wǎng)web后臺", "ws://129.204....:8887")};// 所有連接后臺//外網(wǎng)的自己放到服務(wù)器上
etAddress.setText(serverInfos[0].serverAddress);// 默認(rèn)選擇第一個連接協(xié)議
ArrayAdapter<ServerInfo> serverAdapter = new ArrayAdapter<ServerInfo>(this, android.R.layout
.simple_spinner_item, serverInfos);
spAddress.setAdapter(serverAdapter);
spAddress.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
ServerInfo selectServerInfo = (ServerInfo) spAddress.getItemAtPosition(position);// 選擇連接后臺
etAddress.setText(selectServerInfo.serverAddress);
etDetails.append("當(dāng)前連接后臺:" + selectServerInfo.serverName + "\n");
Log.e("wlf", "當(dāng)前連接后臺:" + selectServerInfo.serverName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
selectDraft = null;// 清空
Log.e("wlf", "未選擇任何連接后臺");
}
});
UserNameInfo[] loginNameInfo = {new UserNameInfo("老鄧", "老鄧"), new UserNameInfo("老鄭", "老鄭"),new UserNameInfo("小金魚", "小金魚"),
new UserNameInfo("張三", "張三"),new UserNameInfo("李四", "李四"),new UserNameInfo("王二", "王二")};// 登錄對象
etloginName.setText(loginNameInfo[0].name);// 默認(rèn)選擇第一個用戶登錄
ArrayAdapter<UserNameInfo> loginNameAdapter = new ArrayAdapter<UserNameInfo>(this, android.R.layout
.simple_spinner_item, loginNameInfo);
sploginName.setAdapter(loginNameAdapter);
sploginName.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
UserNameInfo selectloginNameInfo = (UserNameInfo) sploginName.getItemAtPosition(position);// 選擇連接后臺
etloginName.setText(selectloginNameInfo.name);
etDetails.append("當(dāng)前登錄用戶名:" + selectloginNameInfo.loginName + "\n");
Log.e("wlf", "當(dāng)前登錄用戶名:" + selectloginNameInfo.loginName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
etloginName = null;// 清空
Log.e("wlf", "未選任何登錄對象");
}
});
UserNameInfo[] userNameInfo = {new UserNameInfo("all", "all"),new UserNameInfo("老鄧", "老鄧"), new UserNameInfo("老鄭", "老鄭"),new UserNameInfo("小金魚", "小金魚"),
new UserNameInfo("李四", "李四"), new UserNameInfo("張三", "張三"), new UserNameInfo("王二", "王二")};// 要發(fā)送的對象
ArrayAdapter<UserNameInfo> userNameAdapter = new ArrayAdapter<UserNameInfo>(this, android.R.layout
.simple_spinner_item, userNameInfo);
spName.setAdapter(userNameAdapter);
spName.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
UserNameInfo selectuserNameInfo = (UserNameInfo) spName.getItemAtPosition(position);// 選擇連接后臺
// etName.setText(selectuserNameInfo.name);
etDetails.append("發(fā)送對象:" + selectuserNameInfo.loginName + "\n");
Log.e("wlf", "發(fā)送對象:" + selectuserNameInfo.loginName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// etName = null;// 清空
Log.e("wlf", "未選任何發(fā)送對象");
}
});
btnConnect.setOnClickListener(this);
btnClearDetails.setOnClickListener(this);
btnClose.setOnClickListener(this);
btnSend.setOnClickListener(this);
WebSocketImpl.DEBUG = true;
System.setProperty("java.net.preferIPv6Addresses", "false");
System.setProperty("java.net.preferIPv4Stack", "true");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnConnect:
try {
if (selectDraft == null) {
return;
}
if(etloginName == null){
return;
}
String address = etAddress.getText().toString().trim();
if (address.contains("JSR356-WebSocket")) {
//address += etName.getText().toString().trim();
}
Log.e("wlf", "連接地址:" + address);
client = new WebSocketClient(new URI(address), selectDraft.draft) {
@Override
public void onOpen(final ServerHandshake serverHandshakeData) {
runOnUiThread(new Runnable() {
@Override
public void run() {
etDetails.append("已經(jīng)連接到服務(wù)器【" + getURI() + "】\n");
Log.e("wlf", "已經(jīng)連接到服務(wù)器【" + getURI() + "】");
spDraft.setEnabled(false);
etAddress.setEnabled(false);
spAddress.setEnabled(false);
etloginName.setEnabled(false);
sploginName.setEnabled(false);
btnConnect.setEnabled(false);
//etName.setEnabled(false);
spName.setEnabled(true);
btnClearDetails.setEnabled(true);
btnClose.setEnabled(true);
btnSend.setEnabled(true);
}
});
}
@Override
public void onMessage(final String message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
etDetails.append("獲取到服務(wù)器信息【" + message + "】\n");
Log.e("wlf", "獲取到服務(wù)器信息【" + message + "】");
}
});
}
@Override
public void onClose(final int code, final String reason, final boolean remote) {
runOnUiThread(new Runnable() {
@Override
public void run() {
etDetails.append("斷開服務(wù)器連接【" + getURI() + ",狀態(tài)碼: " + code + "乡洼,斷開原因:" + reason +
"】\n");
Log.e("wlf", "斷開服務(wù)器連接【" + getURI() + "崇裁,狀態(tài)碼: " + code + ",斷開原因:" + reason + "】");
spDraft.setEnabled(true);
etAddress.setEnabled(true);
spAddress.setEnabled(true);
etloginName.setEnabled(true);
sploginName.setEnabled(true);
btnConnect.setEnabled(true);
//etName.setEnabled(true);
spName.setEnabled(false);
btnClearDetails.setEnabled(true);
btnClose.setEnabled(false);
btnSend.setEnabled(false);
}
});
}
@Override
public void onError(final Exception e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
etDetails.append("連接發(fā)生了異呈牵【異常原因:" + e + "】\n");
Log.e("wlf", "連接發(fā)生了異嘲挝龋【異常原因:" + e + "】");
spDraft.setEnabled(true);
etAddress.setEnabled(true);
btnConnect.setEnabled(true);
//etName.setEnabled(true);
btnClearDetails.setEnabled(false);
btnClose.setEnabled(false);
btnSend.setEnabled(false);
}
});
}
};
client.connect();
new Thread(){
@Override
public void run(){
super.run();
try {
Thread.sleep(200);
if (client != null) {
client.send(etloginName.getText().toString().trim());
svChat.post(new Runnable() {
@Override
public void run() {
svChat.fullScroll(View.FOCUS_DOWN);
etMessage.setText("");
etMessage.requestFocus();
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.btnClearDetails:
if (etDetails.getText().toString() != null && etDetails.getText().length()>0) {
etDetails.setText("");
}
break;
case R.id.btnClose:
if (client != null) {
client.close();
}
break;
case R.id.btnSend:
try {
if (client != null) {
//client.send(etName.getText().toString().trim() + "說:" + etMessage.getText().toString().trim());
//client.send(etName.getText().toString().trim() +"@"+etMessage.getText().toString().trim());
client.send(spName.getSelectedItem().toString().trim() +"@"+etMessage.getText().toString().trim());
svChat.post(new Runnable() {
@Override
public void run() {
svChat.fullScroll(View.FOCUS_DOWN);
etMessage.setText("");
etMessage.requestFocus();
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (client != null) {
client.close();
}
}
private class DraftInfo {
private final String draftName;
private final Draft draft;
public DraftInfo(String draftName, Draft draft) {
this.draftName = draftName;
this.draft = draft;
}
@Override
public String toString() {
return draftName;
}
}
private class ServerInfo {
private final String serverName;
private final String serverAddress;
public ServerInfo(String serverName, String serverAddress) {
this.serverName = serverName;
this.serverAddress = serverAddress;
}
@Override
public String toString() {
return serverName;
}
}
private class UserNameInfo {
private final String loginName;
private final String name;
public UserNameInfo(String loginName, String name) {
this.loginName = loginName;
this.name = name;
}
@Override
public String toString() {
return loginName;
}
}
}
現(xiàn)在就可以完成H5和Andorid通信啦