socket(四)Android与socket与LED灯
Android界面设置
由于该项目只完成最简单的LED点灯,所以这里粗略布置一个LED灯开关的按钮即可
<Switch android:id="@+id/LED" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LED" tools:ignore="UseSwitchCompatOrMaterialXml"> </Switch>
运行效果:
代码部分
主界面部分
我们需要定义LED按钮变量与socket连接的变量
Switch sw_led; SocketClient socketClient;
然后重写onCreate方法,这是Activity生命周期中的一个重要方法,用于初始化Activity。
// 调用父类的onCreate方法进行初始化 super.onCreate(savedInstanceState); // 设置布局为activity_main.xml setContentView(R.layout.activity_main); //获取布局中的LED开关控件,并将其赋值给sw_led变量 sw_led = findViewById(R.id.LED);
我们需要创建一个新的SocketClient对象,并启动它来完成socket的工作,并且设置监听事件,当我们点击按钮时,LED发生变化
socketClient = new SocketClient(); socketClient.start(); sw_led.setOnClickListener(v ->{ if (sw_led.isChecked()) { socketClient.sendMessage("LED OFF"); } else { socketClient.sendMessage("LED ON"); } });
所以,整个主函数代码为
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.widget.Button; import android.widget.Switch; public class MainActivity extends AppCompatActivity { Switch sw_led; SocketClient socketClient; @Override protected void onCreate(Bundle savedInstanceState) { // 调用父类的onCreate方法进行初始化 super.onCreate(savedInstanceState); // 设置布局为activity_main.xml setContentView(R.layout.activity_main); //获取布局中的LED开关控件,并将其赋值给sw_led变量 sw_led = findViewById(R.id.LED); socketClient = new SocketClient(); socketClient.start(); sw_led.setOnClickListener(v ->{ if (sw_led.isChecked()) { socketClient.sendMessage("LED OFF"); } else { socketClient.sendMessage("LED ON"); } }); } @Override protected void onResume() { super.onResume(); } }
Socket部分
首先,我们需要定义一些我们需要的变量
String ip; int port; Socket socket; BufferedReader in; BufferedWriter out; Handler handler;
由于java语言的特点,没有信号槽那种机制,所以在Android部分,为了实现信号槽效果,我们采用多线程的方法,方便Android在构建界面的同时能够处理socket通信。
首先,我们需要两个构造参数得到IP与端口,其中一个构造函数是为了方便我们测试
public SocketClient(String ip, int port) { this.ip = ip; this.port = port; } public SocketClient() { this.ip = "192.168.252.244"; this.port = 8888; }
其次,我们要重写run方法,创建新的socket对象,连接到指定的IP与端口号,然后创建输入输出流对象
try { socket = new Socket(ip,port); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); } catch (IOException e) { throw new RuntimeException(e); }
如果碰到了来自于socket的输入,则要去处理他。我们需要不断从输入流中读取数据然后赋值给变量,在控制台通过输出流将信息输出,且更加接收到的指令发送不同的消息
while(true){ try { String msg = in.readLine(); System.out.printf("收到消息:%s\n",msg); if (msg.contains("LED ON")) { handler.sendEmptyMessage(1); } else if (msg.contains("LED OFF")) { handler.sendEmptyMessage(0); } } catch (IOException e) { throw new RuntimeException(e); } }
所以,整个run方法的代码为:
@Override public void run() { try { socket = new Socket(ip,port); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); } catch (IOException e) { throw new RuntimeException(e); } while(true){ try { String msg = in.readLine(); System.out.printf("收到消息:%s\n",msg); if (msg.contains("LED ON")) { handler.sendEmptyMessage(1); } else if (msg.contains("LED OFF")) { handler.sendEmptyMessage(0); } } catch (IOException e) { throw new RuntimeException(e); } } }
发送信息则需要创建一个线程,使用输出流发送信息,发送时记得添加换行符,然后启动线程
void sendMessage(String msg){ new Thread(()->{ try { out.write(msg); out.newLine(); out.flush(); } catch (IOException e) { throw new RuntimeException(e); } }).start(); }
所以整个socket部分的代码为:
package com.example.myapplication; import android.os.Handler; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; public class SocketClient extends Thread{ String ip; int port; Socket socket; BufferedReader in; BufferedWriter out; Handler handler; public SocketClient(String ip, int port) { this.ip = ip; this.port = port; } public SocketClient() { this.ip = "192.168.252.244"; this.port = 8888; } @Override public void run() { try { socket = new Socket(ip,port); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); } catch (IOException e) { throw new RuntimeException(e); } while(true){ try { String msg = in.readLine(); System.out.printf("收到消息:%s\n",msg); if (msg.contains("LED ON")) { handler.sendEmptyMessage(1); } else if (msg.contains("LED OFF")) { handler.sendEmptyMessage(0); } } catch (IOException e) { throw new RuntimeException(e); } } } void sendMessage(String msg){ new Thread(()->{ try { out.write(msg); out.newLine(); out.flush(); } catch (IOException e) { throw new RuntimeException(e); } }).start(); } void setHandler(Handler handler){ this.handler = handler; } }