读书人

SMSLib兑现Java短信收发的功能

发布时间: 2012-12-24 10:43:14 作者: rapoo

SMSLib实现Java短信收发的功能
blog迁移至:http://www.micmiu.com

用java实现短信收发的功能,目前一般项目中短信群发功能的实现方法大致有下面三种:
1、 向运行商申请短信网关,不需要额外的设备,利用运行商提供的API调用程序发送短信,适用于大型的通信公司。2、 借助像GSM MODEM之类的设备(支持AT指令的手机也行),通过数据线连接电脑来发送短信,这种方法比较适用于小公司及个人。要实现这种方式必须理解串口通信、AT指令、短信编码、解码。3、 借助第三方运行的网站实现,由网站代发短信数据,这种方法对网站依赖性太高,对网络的要求也比较高。
鉴于项目的情况和多方考虑,同时又找到了一个开源的SMSLib项目的支持,比较倾向于第二种方法,SMSLib的出现就不需要我们自己去写底层的AT指令,这样就可以直接通过调用SMSLib的API来实现通过GSM modem来收发送短信了。

SMSLib官方网站:http://smslib.org/,使用SMSLib的一些基本要点:
SUN JDK 1.6 or newer. (Java环境)Java Communications Library. (Java串口通信)Apache ANT for building the sources. (编译源码时需要的)Apache log4j. (日志工具)Apache Jakarta Commons - NET. (网络操作相关的)JSMPP Library (SMPP协议时需要的)
有关Java串口通信需要补充说明:
window系统可以用SUN Java Comm v2. (该版本好像也支持solaris) 其下载地址:http://smslib.googlecode.com/files/javacomm20-win32.zip其他操作系统(比如:Linux, Unix, BSD,等等),你可以选择 Java Comm v3 或者是RxTx。 Java Comm v3下载地址:http://java.sun.com/products/javacomm/(需要注册);
RxTx官网:http://users.frii.com/jarvi/rxtx/index.html or http://rxtx.qbang.org/wiki/index.php/Main_Page

附件提供相关下载:
java串口通信v2:javacomm20-win32.zipsmslib-3.5.1.jar短信 modem驱动:PL2303_Prolific_DriverInstaller_v130.zip
本次测试的环境是window,GSM modem是wavecom,所以这次主要描述window环境下简单的实现过程:
【一】、配置相应的环境
首先解压下载的Java Comm v2文件javacomm20-win32.zip,具体配置步骤如下:
把文件:comm.jar copy 到目录:<JDKDIR>/jre/lib/ext/,当然这一步也可以不要这样做,你只需把comm.jar copy到所要运行的项目对应的lib/下既可把文件:javax.comm.properties copy 到目录:<JDKDIR>/jre/lib/把DLL文件:win32com.dll(windows) copy 到目录:<JDKDIR>/jre/bin/如果存在JRE目录, 最好按照上面步骤把文件copy到<JREDIR>相应的目录下
【二】、测试串口端口程序:
TestGetPortList.java

package michael.comm.serial;import java.util.Enumeration;import javax.comm.CommDriver;import javax.comm.CommPortIdentifier;import javax.comm.SerialPort;/** * @author michael *  */public class TestGetPortList {    /**     * @param args     * @throws Exception     */    public static void main(String[] args) throws Exception {        // 人工加载驱动        // MainTest.driverInit();        TestGetPortList.getCommPortList();        // 人工加载驱动获取端口列表        // TestGetPortList.getPortByDriver();    }    /**     * 手工加载驱动<br>     * 正常情况下程序会自动加载驱动,故通常不需要人工加载<br>     * 每重复加载一次,会把端口重复注册,CommPortIdentifier.getPortIdentifiers()获取的端口就会重复     */    public static void driverManualInit() {        String driverName = "com.sun.comm.Win32Driver";        String libname = "win32com";        CommDriver commDriver = null;        try {            System.loadLibrary("win32com");            System.out.println(libname + " Library Loaded");            commDriver = (javax.comm.CommDriver) Class.forName(driverName)                    .newInstance();            commDriver.initialize();            System.out.println("comm Driver Initialized");        } catch (Exception e) {            System.err.println(e);        }    }    /**     * 获取端口列表     */    public static void getCommPortList() {        CommPortIdentifier portId;        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();        while (portEnum.hasMoreElements()) {            portId = (CommPortIdentifier) portEnum.nextElement();            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {                System.out.println("串口: name-" + portId.getName()                        + " 是否占用-" + portId.isCurrentlyOwned());            } else {                System.out.println("并口: name-" + portId.getName()                        + " 是否占用-" + portId.isCurrentlyOwned());            }        }        System.out.println("-------------------------------------");    }    /**     *      */    public static void getPortByDriver() {        String driverName = "com.sun.comm.Win32Driver";        String libname = "win32com";        CommDriver commDriver = null;        try {            System.loadLibrary("win32com");            System.out.println(libname + " Library Loaded");            commDriver = (CommDriver) Class.forName(driverName).newInstance();            commDriver.initialize();            System.out.println("comm Driver Initialized");        } catch (Exception e) {            System.err.println(e);        }        SerialPort sPort = null;        try {            sPort = (SerialPort) commDriver.getCommPort("COM24",                    CommPortIdentifier.PORT_SERIAL);            System.out.println("find CommPort:" + sPort.toString());        } catch (Exception e) {            System.out.println(e.getMessage());        }    }}

本机运行结果:package michael.comm.serial;import java.io.InputStream;import java.io.OutputStream;import java.util.Enumeration;import javax.comm.CommPortIdentifier;import javax.comm.SerialPort;/** * @author michael * */public class TestCommPort { static CommPortIdentifier portId; static Enumeration portList; static int bauds[] = { 9600, 19200, 57600, 115200 }; /** * @param args */ public static void main(String[] args) { portList = CommPortIdentifier.getPortIdentifiers(); System.out.println("GSM Modem 串行端口连接测试开始..."); String portName = "COM24"; while (portList.hasMoreElements()) { portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL && portName.equals(portId.getName())) { System.out.println("找到串口: " + portId.getName()); for (int i = 0; i < bauds.length; i++) { System.out.print(" Trying at " + bauds[i] + "..."); try { SerialPort serialPort; InputStream inStream; OutputStream outStream; int c; StringBuffer response = new StringBuffer(); serialPort = (SerialPort) portId.open( "SMSLibCommTester", 2000); serialPort .setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN); serialPort.setSerialPortParams(bauds[i], SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); inStream = serialPort.getInputStream(); outStream = serialPort.getOutputStream(); serialPort.enableReceiveTimeout(1000); c = inStream.read(); while (c != -1) { c = inStream.read(); } outStream.write('A'); outStream.write('T'); outStream.write('\r'); try { Thread.sleep(1000); } catch (Exception e) { } c = inStream.read(); while (c != -1) { response.append((char) c); c = inStream.read(); } if (response.indexOf("OK") >= 0) { System.out.print(" 正在检测设备:"); try { outStream.write('A'); outStream.write('T'); outStream.write('+'); outStream.write('C'); outStream.write('G'); outStream.write('M'); outStream.write('M'); outStream.write('\r'); response = new StringBuffer(); c = inStream.read(); while (c != -1) { response.append((char) c); c = inStream.read(); } System.out.println(" 发现设备: " + response.toString().replaceAll( "(\\s+OK\\s+)|[\n\r]", "")); } catch (Exception e) { System.out.println(" 检测设备失败,获取设备信息异常:" + e.getMessage()); } } else { System.out.println(" 检测设备失败,有接收到响应结果!"); } serialPort.close(); } catch (Exception e) { System.out.println(" 检测设备失败,发生异常:" + e.getMessage()); } } } } }}
运行结果如下:
package michael.sms;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import org.apache.log4j.Level;import org.apache.log4j.Logger;import org.smslib.AGateway;import org.smslib.GatewayException;import org.smslib.InboundMessage;import org.smslib.OutboundMessage;import org.smslib.Service;import org.smslib.AGateway.Protocols;import org.smslib.Message.MessageEncodings;import org.smslib.modem.SerialModemGateway;/** * @author michael * */public class SmsHandler { private static final Logger logger = Logger.getLogger(SmsHandler.class); private Service smsService; /** * */ public SmsHandler() { smsService = Service.getInstance(); List<AGateway> agatewayList = new ArrayList<AGateway>(); String portName = "COM24";//"/dev/ttyUSB0";// COM24 SerialModemGateway gateway = new SerialModemGateway( "modem." + portName, portName, 9600, "wavecom", "PL2303"); gateway.setInbound(true); gateway.setOutbound(true); gateway.setProtocol(Protocols.PDU); gateway.setSimPin("0000"); agatewayList.add(gateway); try { for (AGateway gatewayTmp : agatewayList) { smsService.addGateway(gatewayTmp); } } catch (GatewayException ex) { logger.error(ex.getMessage()); } } /** * */ public void start() { logger.info("SMS service start....."); try { smsService.startService(); } catch (Exception ex) { logger.error("SMS service start error:", ex); } } /** * */ public void destroy() { try { smsService.stopService(); } catch (Exception ex) { logger.error("SMS service stop error:", ex); } logger.info("SMS service stop"); } /** * send SMS * @param msg * @return Boolean */ public Boolean sendSMS(OutboundMessage msg) { try { msg.setEncoding(MessageEncodings.ENCUCS2); return smsService.sendMessage(msg); } catch (Exception e) { logger.error("send error:", e); } return false; } private boolean isStarted() { if (smsService.getServiceStatus() == Service.ServiceStatus.STARTED) { for (AGateway gateway : smsService.getGateways()) { if (gateway.getStatus() == AGateway.GatewayStatuses.STARTED) { return true; } } } return false; } /** * read SMS * @return List */ public List<InboundMessage> readSMS() { List<InboundMessage> msgList = new LinkedList<InboundMessage>(); if (!isStarted()) { return msgList; } try { this.smsService.readMessages(msgList, InboundMessage.MessageClasses.ALL); logger.info("read SMS size: " + msgList.size()); } catch (Exception e) { logger.error("read error:", e); } return msgList; } /** * @param args */ public static void main(String[] args) { Logger.getRootLogger().setLevel(Level.INFO); OutboundMessage outMsg = new OutboundMessage("189xxxx****", "信息测试"); SmsHandler smsHandler = new SmsHandler(); smsHandler.start(); //发送短信 smsHandler.sendSMS(outMsg); //读取短信 List<InboundMessage> readList = smsHandler.readSMS(); for (InboundMessage in : readList) { System.out.println("发信人:" + in.getOriginator() + " 短信内容:" + in.getText()); } smsHandler.destroy(); System.out.println("-----------"); }}
发送短信亲测,手机能正常接收显示。读取设备的短信程序运行结果结果如下:
5 楼 liminshaoye 2012-05-05 为什么不能重复发送短信? 6 楼 liminshaoye 2012-05-05 第二次会发送失败发送不了?请问怎么解决? 7 楼 sjsky 2012-05-06 liminshaoye 写道第二次会发送失败发送不了?请问怎么解决?
你说的“第二次”,不知道你是指通一条短信发两次 还是 重复调用发送的 方法 失败 8 楼 chensong215 2012-07-20 用厦门宇能的短信 猫,调用InboundMessage的getText()方法就出错了,提示不支持 9 楼 chensong215 2012-07-20 chensong215 写道用厦门宇能的短信 猫,调用InboundMessage的getText()方法就出错了,提示不支持
不知各位有没有遇到过?是怎么解决的? 10 楼 evil850209 2012-09-24 如何调用usb端口的设备呢?我这只能显示出来COM1口,其他的串口都没有

读书人网 >编程

热点推荐