You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java向GSM Modem发送AT+CMGR/AT+CMGL指令读取并打印短信?

用Java结合RXTX实现短信读取与删除

我完全理解作为新手在接触RXTX、Java串口通信和AT指令时的迷茫——你已经成功搞定了串口检测,这已经是非常好的开端了!接下来我就一步步给你实现读取收到的短信、打印内容并删除的Java代码,同时解释每个部分的作用,帮你理清逻辑。

先明确核心AT指令的作用

咱们先把要用到的关键AT指令搞清楚:

  • AT+CMGL="ALL":列出所有短信(包括已读、未读),返回每条短信的索引、状态、发送方号码、时间和内容
  • AT+CMGR=<索引>:读取指定索引的单条短信(如果只是批量读取,用CMGL更高效)
  • AT+CMGD=<索引>:删除指定索引的短信

完整实现代码

下面的代码是在你现有串口检测代码的基础上扩展的,包含了串口打开、AT指令发送、短信解析和删除的完整逻辑:

package anothersms;

import gnu.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;

public class SMSReader {
    private SerialPort serialPort;
    private OutputStream outputStream;
    private BufferedReader inputReader;

    // 串口参数配置(要和你的短信模块参数一致,常见是9600波特率)
    private static final int BAUD_RATE = 9600;
    private static final int DATA_BITS = SerialPort.DATABITS_8;
    private static final int STOP_BITS = SerialPort.STOPBITS_1;
    private static final int PARITY = SerialPort.PARITY_NONE;

    public static void main(String[] args) {
        SMSReader smsReader = new SMSReader();
        // 先检测可用串口,你可以选择要连接的串口名称,比如"COM3"
        String targetPort = smsReader.detectAvailablePorts();
        if (targetPort == null) {
            System.out.println("未找到可用串口!");
            return;
        }
        System.out.println("尝试连接串口:" + targetPort);
        
        // 打开串口并初始化
        if (smsReader.openSerialPort(targetPort)) {
            // 初始化短信模块(发送AT指令确认连接)
            if (smsReader.sendATCommand("AT") != null) {
                System.out.println("模块连接成功!");
                // 读取并处理所有短信
                smsReader.readAndProcessSMS();
            } else {
                System.out.println("模块连接失败!");
            }
            // 关闭串口
            smsReader.closeSerialPort();
        } else {
            System.out.println("串口打开失败!");
        }
    }

    // 检测可用串口(复用你原来的代码)
    private String detectAvailablePorts() {
        System.out.println("正在检测可用串口...");
        CommPortIdentifier serialPortId;
        Enumeration enumComm = CommPortIdentifier.getPortIdentifiers();
        String firstPort = null;
        while (enumComm.hasMoreElements()) {
            serialPortId = (CommPortIdentifier) enumComm.nextElement();
            if (serialPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                System.out.println("找到串口:" + serialPortId.getName());
                if (firstPort == null) {
                    firstPort = serialPortId.getName();
                }
            }
        }
        return firstPort;
    }

    // 打开指定串口
    private boolean openSerialPort(String portName) {
        try {
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
            // 打开串口,超时时间2000ms
            CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
            if (commPort instanceof SerialPort) {
                serialPort = (SerialPort) commPort;
                // 设置串口参数
                serialPort.setSerialPortParams(BAUD_RATE, DATA_BITS, STOP_BITS, PARITY);
                // 获取输入输出流
                outputStream = serialPort.getOutputStream();
                inputReader = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
                return true;
            } else {
                System.out.println("指定端口不是串口!");
            }
        } catch (NoSuchPortException | PortInUseException | UnsupportedCommOperationException | IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    // 发送AT指令并返回响应
    private String sendATCommand(String command) {
        try {
            // 发送指令,注意要加\r\n结尾(AT指令的标准结束符)
            outputStream.write((command + "\r\n").getBytes());
            outputStream.flush();
            // 读取响应,这里简单读取所有返回内容
            StringBuilder response = new StringBuilder();
            Thread.sleep(1000); // 等待模块响应,根据实际情况调整时间
            while (inputReader.ready()) {
                response.append(inputReader.readLine()).append("\n");
            }
            return response.toString();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 读取所有短信并处理(打印+删除)
    private void readAndProcessSMS() {
        // 发送读取所有短信的指令
        String smsResponse = sendATCommand("AT+CMGL=\"ALL\"");
        if (smsResponse == null || !smsResponse.contains("OK")) {
            System.out.println("读取短信失败!");
            return;
        }
        System.out.println("\n=== 读取到的短信内容 ===");
        // 解析短信响应,拆分每条短信
        String[] smsLines = smsResponse.split("\n");
        for (int i = 0; i < smsLines.length; i++) {
            String line = smsLines[i].trim();
            // 短信索引行格式:+CMGL: <索引>,<状态>,<号码>,"",<时间>
            if (line.startsWith("+CMGL:")) {
                // 提取索引
                String[] parts = line.split(",");
                int smsIndex = Integer.parseInt(parts[0].split(":")[1].trim());
                String senderNumber = parts[2].replace("\"", "");
                String smsTime = parts[4].replace("\"", "");
                // 下一行是短信内容
                String smsContent = smsLines[i + 1].trim();
                // 打印短信信息
                System.out.println("短信索引:" + smsIndex);
                System.out.println("发送方:" + senderNumber);
                System.out.println("时间:" + smsTime);
                System.out.println("内容:" + smsContent);
                System.out.println("------------------------");
                
                // 删除这条短信
                String deleteResponse = sendATCommand("AT+CMGD=" + smsIndex);
                if (deleteResponse != null && deleteResponse.contains("OK")) {
                    System.out.println("索引" + smsIndex + "的短信已删除");
                } else {
                    System.out.println("索引" + smsIndex + "的短信删除失败");
                }
            }
        }
    }

    // 关闭串口资源
    private void closeSerialPort() {
        try {
            if (inputReader != null) {
                inputReader.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
            if (serialPort != null) {
                serialPort.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

关键细节说明

  1. 串口参数匹配:代码里的波特率、数据位等参数必须和你的短信模块一致,大部分模块默认是9600波特率,如果不对可以调整BAUD_RATE的值。
  2. AT指令结束符:所有AT指令必须以\r\n结尾,这是串口通信的标准要求,不然模块可能不响应。
  3. 响应等待时间:发送指令后要给模块一点处理时间,代码里用Thread.sleep(1000),如果你的模块响应慢,可以适当延长时间。
  4. 短信解析逻辑:AT+CMGL的响应格式是固定的,我们通过识别+CMGL:开头的行来提取短信索引、号码等信息,下一行就是短信内容,这个解析逻辑可以根据你的模块返回的格式微调。

注意事项

  • 确保你已经正确配置了RXTX的DLL文件(32位/64位要和JVM匹配),不然代码会抛出找不到库的异常。
  • 测试时要确保短信模块已经正确连接到电脑串口,并且模块处于正常工作状态(可以用串口助手先发送AT指令测试模块是否响应)。

内容的提问来源于stack exchange,提问作者ikiSiTamvaaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:13