新的开始,新的知识。
在学习安卓的过程中,有一个是关于做石头剪刀布游戏的左右,我设法想实现人对人对战,正好想尝试一下websocket编程,本篇先写的是websocket客户端。
服务端可参考:
https://blog.youkuaiyun.com/Abit_Go/article/details/105702517
实现现象:
首先添加库配置文件。
implementation 'com.squareup.okhttp3:okhttp:3.14.2'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.alibaba:fastjson:1.1.71.android'
其次设定开始页面,用来输入用户名
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:ignore="NamespaceTypo">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="10dp"
android:text="欢迎来到石头剪刀布游戏"
android:textColor="#000000"
android:textSize="30dp" />
<EditText
android:layout_below="@+id/tv1"
android:id="@+id/roomId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入联机名字"
android:paddingLeft="10dp"
android:paddingTop="20dp"
android:paddingRight="10dp" />
<LinearLayout
android:layout_below="@+id/roomId"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginTop="5dp"
android:text="进入房间" />
<Button
android:id="@+id/single"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="200dp"
android:layout_marginTop="5dp"
android:text="人机对战" />
</LinearLayout>
</RelativeLayout >
然后分别是游玩界面。
<?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"
tools:ignore="NamespaceTypo">
<TextView
android:paddingTop="20dp"
android:layout_gravity="center"
android:id="@+id/msg"
android:textColor="#000000"
android:textSize="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="石头剪刀布"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:paddingTop="20dp"
android:textSize="40dp"
android:layout_gravity="center"
android:text="显示消息"
android:id="@+id/showMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:paddingTop="20dp"
android:layout_gravity="center"
android:text="挑战结果:"
android:textSize="20dp"
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:paddingTop="40dp"
android:layout_gravity="center"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_gravity="center_vertical"
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上一个" />
<ImageButton
android:layout_gravity="center"
android:src="@mipmap/shitou"
android:id="@+id/iv1"
android:layout_width="500px"
android:layout_height="500px" />
<Button
android:layout_gravity="center_vertical"
android:text="下一个"
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:layout_gravity="center"
android:enabled="true"
android:text="提交"
android:id="@+id/submitJSON"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout >
最后是逻辑代码部分:
开始界面逻辑代码:
package com.example.game;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class ActivityStart extends AppCompatActivity {
private EditText editText;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start);
initView();
}
void initView(){
editText = findViewById(R.id.roomId);
button = findViewById(R.id.submit);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(ActivityStart.this,ActivityPlay.class);
String roomId = editText.getText().toString();
intent.putExtra("roomId",roomId);
if(roomId.equals("")){
Toast.makeText(ActivityStart.this,"房间号不能为空",Toast.LENGTH_SHORT).show();
}
startActivity(intent);
}
});
}
}
游玩界面源码:
package com.example.game;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class ActivityPlay extends AppCompatActivity {
private TextView textView;
private Button left;
private Button right;
private ImageButton imageView;
private int index = 0;
private Button submit;
private WebSocket mSocket;
private String name;
//初始状态
private int send=-1;
private int value_0=-1;
private TextView result;
private int[] imgIndex = {R.mipmap.shitou, R.mipmap.jiandao, R.mipmap.bu};
private String[] imgContant = {"石头","剪刀","布"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playinterface);
initView();
start();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.arg1){
case 1:
//连接成功
textView.setText(msg.obj.toString());
break;
case 2:
//接收到的消息
String receive = msg.obj.toString();
JSONObject jsonObject = JSONObject.parseObject(receive);
value_0= jsonObject.getIntValue("value");
String name_O = jsonObject.getString("name");
//如果是自己发起的,那就直接接收即可
if (send==0){
send = -1;
submit.setEnabled(true);
if(value_0==index){
result.setText("结果:平局");
}else {
if((index+1)%3==value_0){
result.setText("结果:你赢了");
}else {
result.setText("结果:你输了");
}
}
}
//如果send等于-1的时候,证明是别人发过来的,
else if(send==-1){
textView.setText("请尽快猜拳");
submit.setEnabled(true);
//如果不是自己自己发起的,那就需要进行下一步的提交
send = 0;
}
break;
case 3:
//关闭
textView.setText(msg.obj.toString());
break;
case 4:
//失败
textView.setText(msg.obj.toString());
break;
}
}
};
private void start() {
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.readTimeout(3, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(3, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(3, TimeUnit.SECONDS)//设置连接超时时间
.build();
Request request = new Request.Builder().url("ws://*.*.*.*:8989/websocket/"+name).build();
EchoWebSocketListener socketListener = new EchoWebSocketListener();
mOkHttpClient.newWebSocket(request, socketListener);
mOkHttpClient.dispatcher().executorService().shutdown();
}
void initView() {
textView = findViewById(R.id.showMsg);
final Intent intent = getIntent();
name = intent.getStringExtra("roomId");
textView.setText(name);
left = findViewById(R.id.left);
left.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
index = ((index + 3) - 1) % 3;
imageView.setImageResource(imgIndex[index]);
}
});
right = findViewById(R.id.right);
right.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
index = ((index + 3) + 1) % 3;
imageView.setImageResource(imgIndex[index]);
}
});
imageView = findViewById(R.id.iv1);
submit = findViewById(R.id.submitJSON);
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//自己先提交的数据
//只要发送以下自己的名字以及index值即可
if(send==-1){
send = 0;
JSONObject jsonObject= new JSONObject();
jsonObject.put("name",name);
jsonObject.put("value",index);
submit.setEnabled(false);
textView.setText("等待对方答映");
mSocket.send(jsonObject.toString());
}
//如果是0的时候那就是别人发过来的状态
else if(send==0) {//true
//如果是别人先提交的数据
send = -1;
if(value_0==index){
result.setText("结果:平局");
}else {
if((index+1)%3==value_0){
result.setText("结果:你赢了");
}else {
result.setText("结果:你输了");
}
}
JSONObject jsonObject= new JSONObject();
jsonObject.put("name",name);
jsonObject.put("value",index);
submit.setEnabled(true);
mSocket.send(jsonObject.toString());
}
}
});
result = findViewById(R.id.result);
}
private final class EchoWebSocketListener extends WebSocketListener {
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
mSocket = webSocket;
// String openid = "img1";
// //连接成功后,发送登录信息
// String message = "{\"type\":\"login\",\"user_id\":\"" + openid + "\"}";
// mSocket.send(message);
showInfo(1,"连接成功!");
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
//接收消息
}
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
showInfo(2,text);
//收到服务器端发送来的信息后,每隔25秒发送一次心跳包
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
mSocket.send("heartbeat");
}
}, 25000);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
//关闭
showInfo(3,"closed:" + reason);
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
super.onClosing(webSocket, code, reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
showInfo(4,"failure:" + t.getMessage());
}
}
void showInfo(int kind,String s){
Message message = new Message();
message.arg1=kind;
message.obj = s;
handler.sendMessage(message);
}
}