socket(四)Android与socket与LED灯

发布时间 2024-01-13 16:38:06作者: 山远尽成云

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;
    }
}