Only the basic communication function is realized, and no Service
andHandle
Reference resources:
SpringBoot uses WebSocket (1)
Implementation of Android WebSocket long connection
achieve effect
Server
The core code is as follows
@ServerEndpoint("/test")
@Component
@Slf4j
public class WebSocketController {
/**
* 存放所有在线的客户端
*/
private static Map<String, Session> clients = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session) {
log.info("有新的客户端连接了: {}", session.getId());
//将新用户存入在线的组
clients.put(session.getId(), session);
}
/**
* 客户端关闭
*
* @param session session
*/
@OnClose
public void onClose(Session session) {
log.info("有用户断开了, id为:{}", session.getId());
//将掉线的用户移除在线的组里
clients.remove(session.getId());
}
/**
* 发生错误
*
* @param throwable e
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
/**
* 收到客户端发来消息
*
* @param message 消息对象
*/
@OnMessage
public void onMessage(String message) {
log.info("服务端收到客户端发来的消息: {}", message);
// 将消息repead一下 发送给所有在线的Client
this.sendAll(message + message);
}
/**
* 群发消息
*
* @param message 消息内容
*/
private void sendAll(String message) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
sessionEntry.getValue().getAsyncRemote().sendText(message);
}
}
}
The effect of using PostMan test is shown in the following figure:
Android client
The first step is to add dependencies
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'org.java-websocket:Java-WebSocket:1.5.2'
The second step is to grant network permissions in the manifest file
<uses-permission android:name="android.permission.INTERNET"/>
The third step is to create ViewModel
public class MyViewModel extends ViewModel {
private final MutableLiveData<String> mName = new MutableLiveData<>();
private final MutableLiveData<String> mMsg = new MutableLiveData<>();
// getter...
}
The fourth step is to write the page
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="work.wxmx.socketclient.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:hint="Msg"
android:layout_width="215dp"
android:layout_height="49dp"
android:inputType="textPersonName"
android:text="@={viewModel.msg}"
android:ems="10"
android:id="@+id/msg_edit_text"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.9"
app:layout_constraintVertical_bias="1.0"
app:layout_constraintEnd_toStartOf="@+id/send_button"
app:layout_constraintStart_toEndOf="@+id/name_edit_text"
android:layout_marginBottom="40dp" />
<Button
android:text="Send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/send_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintVertical_bias="1.0"
android:layout_marginRight="8dp"
android:layout_marginBottom="40dp" />
<EditText
android:text="@={viewModel.name}"
android:layout_width="80dp"
android:layout_height="42dp"
android:inputType="textPersonName"
android:hint="Name"
android:ems="10"
android:id="@+id/name_edit_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="40dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp" />
<TextView
android:text="AAA"
android:textSize="30sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/msg_text_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="50dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
The effect diagram is shown in the figure below:
The fifth step is to implement WebSockClient
public class MyWebSocket extends WebSocketClient {
private static final String TAG = "TAG";
private SocketListener mSocketListener;
public MyWebSocket(URI serverUri) {
super(serverUri);
}
public MyWebSocket(URI serverUri, Draft protocolDraft) {
super(serverUri, protocolDraft);
}
@Override
public void onOpen(ServerHandshake handshakedata) {
Log.e(TAG, "onOpen: ");
}
@Override
public void onMessage(String message) {
mSocketListener.onMessage(message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
Log.e(TAG, "onClose: ");
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
Log.e(TAG, "onError: ");
}
public interface SocketListener {
void onMessage(String msg);
}
public SocketListener getSocketListener() {
return mSocketListener;
}
public void setSocketListener(SocketListener socketListener) {
mSocketListener = socketListener;
}
}
The sixth step is to write Activity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TAG";
ActivityMainBinding mBinding;
MyViewModel mViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mBinding.getRoot());
mViewModel = new ViewModelProvider(this).get(MyViewModel.class);
mBinding.setViewModel(mViewModel);
URI uri = URI.create("ws://10.0.2.2:8080/test");
MyWebSocket webSocket = new MyWebSocket(uri);
webSocket.setSocketListener(mSocketListener);
try {
boolean b = webSocket.connectBlocking(4, TimeUnit.SECONDS);
Log.e(TAG, "onCreate: " + b);
if (b) {
} else {
}
} catch (InterruptedException e) {
e.printStackTrace();
}
mBinding.sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (webSocket.isOpen()) {
String name = mViewModel.getName().getValue();
String msg = mViewModel.getMsg().getValue();
String sendData = name +msg;
Log.e(TAG, "onClick: " + sendData);
webSocket.send(sendData);
} else {
webSocket.reconnect();
Log.e(TAG, "onClick: web socket is not open");
}
}
});
}
private MyWebSocket.SocketListener mSocketListener = new MyWebSocket.SocketListener() {
@Override
public void onMessage(String msg) {
Log.e(TAG, "onMessage: " + msg);
mBinding.msgTextView.setText(mBinding.msgTextView.getText() + "" + msg);
}
};
}