SMSLib实现Java短信收发的功能

摘选:http://sjsky.iteye.com/blog/1045502 

用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,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

Java代码   收藏代码
  1. package  michael.comm.serial;  
  2.   
  3. import  java.util.Enumeration;  
  4.   
  5. import  javax.comm.CommDriver;  
  6. import  javax.comm.CommPortIdentifier;  
  7. import  javax.comm.SerialPort;  
  8.   
  9. /**  
  10.  * @author michael  
  11.  *   
  12.  */   
  13. public   class  TestGetPortList {  
  14.   
  15.     /**  
  16.      * @param args  
  17.      * @throws Exception  
  18.      */   
  19.     public   static   void  main(String[] args)  throws  Exception {  
  20.         // 人工加载驱动   
  21.         // MainTest.driverInit();   
  22.         TestGetPortList.getCommPortList();  
  23.         // 人工加载驱动获取端口列表   
  24.         // TestGetPortList.getPortByDriver();   
  25.   
  26.     }  
  27.   
  28.     /**  
  29.      * 手工加载驱动<br>  
  30.      * 正常情况下程序会自动加载驱动,故通常不需要人工加载<br>  
  31.      * 每重复加载一次,会把端口重复注册,CommPortIdentifier.getPortIdentifiers()获取的端口就会重复  
  32.      */   
  33.     public   static   void  driverManualInit() {  
  34.         String driverName = "com.sun.comm.Win32Driver" ;  
  35.         String libname = "win32com" ;  
  36.         CommDriver commDriver = null ;  
  37.         try  {  
  38.             System.loadLibrary("win32com" );  
  39.             System.out.println(libname + " Library Loaded" );  
  40.   
  41.             commDriver = (javax.comm.CommDriver) Class.forName(driverName)  
  42.                     .newInstance();  
  43.             commDriver.initialize();  
  44.             System.out.println("comm Driver Initialized" );  
  45.   
  46.         } catch  (Exception e) {  
  47.             System.err.println(e);  
  48.         }  
  49.     }  
  50.   
  51.     /**  
  52.      * 获取端口列表  
  53.      */   
  54.     public   static   void  getCommPortList() {  
  55.         CommPortIdentifier portId;  
  56.         Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();  
  57.         while  (portEnum.hasMoreElements()) {  
  58.             portId = (CommPortIdentifier) portEnum.nextElement();  
  59.   
  60.             if  (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {  
  61.                 System.out.println("串口: name-"  + portId.getName()  
  62.                         + " 是否占用-"  + portId.isCurrentlyOwned());  
  63.             } else  {  
  64.                 System.out.println("并口: name-"  + portId.getName()  
  65.                         + " 是否占用-"  + portId.isCurrentlyOwned());  
  66.             }  
  67.         }  
  68.         System.out.println("-------------------------------------" );  
  69.     }  
  70.   
  71.     /**  
  72.      *   
  73.      */   
  74.     public   static   void  getPortByDriver() {  
  75.   
  76.         String driverName = "com.sun.comm.Win32Driver" ;  
  77.         String libname = "win32com" ;  
  78.         CommDriver commDriver = null ;  
  79.         try  {  
  80.             System.loadLibrary("win32com" );  
  81.             System.out.println(libname + " Library Loaded" );  
  82.   
  83.             commDriver = (CommDriver) Class.forName(driverName).newInstance();  
  84.             commDriver.initialize();  
  85.             System.out.println("comm Driver Initialized" );  
  86.   
  87.         } catch  (Exception e) {  
  88.             System.err.println(e);  
  89.         }  
  90.         SerialPort sPort = null ;  
  91.         try  {  
  92.   
  93.             sPort = (SerialPort) commDriver.getCommPort("COM24" ,  
  94.                     CommPortIdentifier.PORT_SERIAL);  
  95.             System.out.println("find CommPort:"  + sPort.toString());  
  96.         } catch  (Exception e) {  
  97.             System.out.println(e.getMessage());  
  98.         }  
  99.   
  100.     }  
  101.   
  102. }  


本机运行结果:

引用

串口: name-COM10 是否占用-false
串口: name-COM21 是否占用-false
串口: name-COM23 是否占用-false
串口: name-COM20 是否占用-false
串口: name-COM22 是否占用-false
串口: name-COM24 是否占用-false
串口: name-COM9 是否占用-false
串口: name-COM19 是否占用-false
串口: name-COM3 是否占用-false
串口: name-COM8 是否占用-false
串口: name-COM98 是否占用-false
串口: name-COM99 是否占用-false
串口: name-COM4 是否占用-false
串口: name-COM5 是否占用-false
串口: name-COM6 是否占用-false
并口: name-LPT1 是否占用-false
并口: name-LPT2 是否占用-false
-------------------------------------


【三】、检查串口设备信息:
TestCommPort.java

Java代码   收藏代码
  1. package  michael.comm.serial;  
  2.   
  3. import  java.io.InputStream;  
  4. import  java.io.OutputStream;  
  5. import  java.util.Enumeration;  
  6.   
  7. import  javax.comm.CommPortIdentifier;  
  8. import  javax.comm.SerialPort;  
  9.   
  10. /**  
  11.  * @author michael  
  12.  *   
  13.  */   
  14. public   class  TestCommPort {  
  15.     static  CommPortIdentifier portId;  
  16.     static  Enumeration portList;  
  17.     static   int  bauds[] = {  9600 19200 57600 115200  };  
  18.   
  19.     /**  
  20.      * @param args  
  21.      */   
  22.     public   static   void  main(String[] args) {  
  23.         portList = CommPortIdentifier.getPortIdentifiers();  
  24.         System.out.println("GSM Modem 串行端口连接测试开始..." );  
  25.         String portName = "COM24" ;  
  26.         while  (portList.hasMoreElements()) {  
  27.             portId = (CommPortIdentifier) portList.nextElement();  
  28.             if  (portId.getPortType() == CommPortIdentifier.PORT_SERIAL  
  29.                     && portName.equals(portId.getName())) {  
  30.                 System.out.println("找到串口: "  + portId.getName());  
  31.                 for  ( int  i =  0 ; i < bauds.length; i++) {  
  32.                     System.out.print("  Trying at "  + bauds[i] +  "..." );  
  33.                     try  {  
  34.                         SerialPort serialPort;  
  35.                         InputStream inStream;  
  36.                         OutputStream outStream;  
  37.                         int  c;  
  38.                         StringBuffer response = new  StringBuffer();  
  39.                         serialPort = (SerialPort) portId.open(  
  40.                                 "SMSLibCommTester" 2000 );  
  41.                         serialPort  
  42.                                 .setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN);  
  43.                         serialPort.setSerialPortParams(bauds[i],  
  44.                                 SerialPort.DATABITS_8, SerialPort.STOPBITS_1,  
  45.                                 SerialPort.PARITY_NONE);  
  46.                         inStream = serialPort.getInputStream();  
  47.                         outStream = serialPort.getOutputStream();  
  48.                         serialPort.enableReceiveTimeout(1000 );  
  49.                         c = inStream.read();  
  50.                         while  (c != - 1 ) {  
  51.                             c = inStream.read();  
  52.                         }  
  53.                         outStream.write('A' );  
  54.                         outStream.write('T' );  
  55.                         outStream.write('\r' );  
  56.                         try  {  
  57.                             Thread.sleep(1000 );  
  58.                         } catch  (Exception e) {  
  59.                         }  
  60.                         c = inStream.read();  
  61.                         while  (c != - 1 ) {  
  62.                             response.append((char ) c);  
  63.                             c = inStream.read();  
  64.                         }  
  65.                         if  (response.indexOf( "OK" ) >=  0 ) {  
  66.                             System.out.print("  正在检测设备:" );  
  67.                             try  {  
  68.                                 outStream.write('A' );  
  69.                                 outStream.write('T' );  
  70.                                 outStream.write('+' );  
  71.                                 outStream.write('C' );  
  72.                                 outStream.write('G' );  
  73.                                 outStream.write('M' );  
  74.                                 outStream.write('M' );  
  75.                                 outStream.write('\r' );  
  76.                                 response = new  StringBuffer();  
  77.                                 c = inStream.read();  
  78.                                 while  (c != - 1 ) {  
  79.                                     response.append((char ) c);  
  80.                                     c = inStream.read();  
  81.                                 }  
  82.                                 System.out.println("  发现设备: "   
  83.                                         + response.toString().replaceAll(  
  84.                                                 "(\\s+OK\\s+)|[\n\r]" "" ));  
  85.                             } catch  (Exception e) {  
  86.                                 System.out.println("  检测设备失败,获取设备信息异常:"   
  87.                                         + e.getMessage());  
  88.                             }  
  89.                         } else  {  
  90.                             System.out.println("  检测设备失败,沒有接收到响应结果!" );  
  91.                         }  
  92.                         serialPort.close();  
  93.                     } catch  (Exception e) {  
  94.                         System.out.println("  检测设备失败,发生异常:"  + e.getMessage());  
  95.                     }  
  96.                 }  
  97.             }  
  98.         }  
  99.     }  
  100. }  


运行结果如下:

引用

GSM Modem 串行端口连接测试开始...
找到串口: COM24
  Trying at 9600...  正在检测设备:  发现设备: AT+CGMM MULTIBAND  900E  1800
  Trying at 19200...  发现设备失败,沒有接收到响应结果!
  Trying at 57600...  发现设备失败,沒有接收到响应结果!
  Trying at 115200...  发现设备失败,沒有接收到响应结果!



【四】、测试收发短信:

Java代码   收藏代码
  1. package  michael.sms;  
  2.   
  3. import  java.util.ArrayList;  
  4. import  java.util.LinkedList;  
  5. import  java.util.List;  
  6.   
  7. import  org.apache.log4j.Level;  
  8. import  org.apache.log4j.Logger;  
  9. import  org.smslib.AGateway;  
  10. import  org.smslib.GatewayException;  
  11. import  org.smslib.InboundMessage;  
  12. import  org.smslib.OutboundMessage;  
  13. import  org.smslib.Service;  
  14. import  org.smslib.AGateway.Protocols;  
  15. import  org.smslib.Message.MessageEncodings;  
  16. import  org.smslib.modem.SerialModemGateway;  
  17.   
  18. /**  
  19.  * @author michael  
  20.  *   
  21.  */   
  22. public   class  SmsHandler {  
  23.     private   static   final  Logger logger = Logger.getLogger(SmsHandler. class );  
  24.   
  25.     private  Service smsService;  
  26.   
  27.     /**  
  28.      *   
  29.      */   
  30.     public  SmsHandler() {  
  31.         smsService = Service.getInstance();  
  32.         List<AGateway> agatewayList = new  ArrayList<AGateway>();  
  33.   
  34.         String portName = "COM24" ; //"/dev/ttyUSB0";// COM24   
  35.         SerialModemGateway gateway = new  SerialModemGateway(  
  36.                 "modem."  + portName, portName,  9600 "wavecom" "PL2303" );  
  37.         gateway.setInbound(true );  
  38.         gateway.setOutbound(true );  
  39.         gateway.setProtocol(Protocols.PDU);  
  40.         gateway.setSimPin("0000" );  
  41.         agatewayList.add(gateway);  
  42.         try  {  
  43.             for  (AGateway gatewayTmp : agatewayList) {  
  44.                 smsService.addGateway(gatewayTmp);  
  45.             }  
  46.         } catch  (GatewayException ex) {  
  47.             logger.error(ex.getMessage());  
  48.         }  
  49.     }  
  50.   
  51.     /**  
  52.      *   
  53.      */   
  54.     public   void  start() {  
  55.         logger.info("SMS service start....." );  
  56.         try  {  
  57.             smsService.startService();  
  58.         } catch  (Exception ex) {  
  59.             logger.error("SMS service start error:" , ex);  
  60.         }  
  61.     }  
  62.   
  63.     /**  
  64.      *   
  65.      */   
  66.     public   void  destroy() {  
  67.         try  {  
  68.             smsService.stopService();  
  69.         } catch  (Exception ex) {  
  70.             logger.error("SMS service stop error:" , ex);  
  71.         }  
  72.         logger.info("SMS service stop" );  
  73.     }  
  74.   
  75.     /**  
  76.      * send SMS  
  77.      * @param msg  
  78.      * @return Boolean  
  79.      */   
  80.     public  Boolean sendSMS(OutboundMessage msg) {  
  81.         try  {  
  82.             msg.setEncoding(MessageEncodings.ENCUCS2);  
  83.             return  smsService.sendMessage(msg);  
  84.         } catch  (Exception e) {  
  85.             logger.error("send error:" , e);  
  86.         }  
  87.         return   false ;  
  88.     }  
  89.   
  90.     private   boolean  isStarted() {  
  91.         if  (smsService.getServiceStatus() == Service.ServiceStatus.STARTED) {  
  92.             for  (AGateway gateway : smsService.getGateways()) {  
  93.                 if  (gateway.getStatus() == AGateway.GatewayStatuses.STARTED) {  
  94.                     return   true ;  
  95.                 }  
  96.             }  
  97.         }  
  98.         return   false ;  
  99.     }  
  100.   
  101.     /**  
  102.      * read SMS  
  103.      * @return List  
  104.      */   
  105.     public  List<InboundMessage> readSMS() {  
  106.         List<InboundMessage> msgList = new  LinkedList<InboundMessage>();  
  107.         if  (!isStarted()) {  
  108.             return  msgList;  
  109.         }  
  110.         try  {  
  111.             this .smsService.readMessages(msgList,  
  112.                     InboundMessage.MessageClasses.ALL);  
  113.             logger.info("read SMS size: "  + msgList.size());  
  114.         } catch  (Exception e) {  
  115.             logger.error("read error:" , e);  
  116.         }  
  117.         return  msgList;  
  118.     }  
  119.   
  120.     /**  
  121.      * @param args  
  122.      */   
  123.     public   static   void  main(String[] args) {  
  124.         Logger.getRootLogger().setLevel(Level.INFO);  
  125.         OutboundMessage outMsg = new  OutboundMessage( "189xxxx****" "信息测试" );  
  126.         SmsHandler smsHandler = new  SmsHandler();  
  127.         smsHandler.start();  
  128.         //发送短信   
  129.         smsHandler.sendSMS(outMsg);  
  130.         //读取短信   
  131.         List<InboundMessage> readList = smsHandler.readSMS();  
  132.         for  (InboundMessage in : readList) {  
  133.             System.out.println("发信人:"  + in.getOriginator() +  " 短信内容:"   
  134.                     + in.getText());  
  135.         }  
  136.         smsHandler.destroy();  
  137.         System.out.println("-----------" );  
  138.     }  
  139.   
  140. }  


发送短信亲测,手机能正常接收显示。读取设备的短信程序运行结果结果如下:

引用

INFO - Service.listSystemInformation(113) | SMSLib: A Java API library for sending and receiving SMS via a GSM modem or other supported gateways.
This software is distributed under the terms of the Apache v2.0 License.
Web Site: http://smslib.org
INFO - Service.listSystemInformation(114) | Version: 3.5.1
INFO - Service.listSystemInformation(115) | JRE Version: 1.6.0_18
INFO - Service.listSystemInformation(116) | JRE Impl Version: 16.0-b13
INFO - Service.listSystemInformation(117) | O/S: Windows Vista / x86 / 6.0
INFO - SmsHandler.start(55) | SMS service start.....
INFO - DefaultQueueManager.init(92) | Queue directory not defined. Queued messages will not be saved to filesystem.
INFO - ModemGateway.startGateway(188) | GTW: modem.COM24: Starting gateway, using Generic AT Handler.
INFO - SerialModemDriver.connectPort(68) | GTW: modem.COM24: Opening: COM24 @9600
INFO - AModemDriver.waitForNetworkRegistration(459) | GTW: modem.COM24: GSM: Registered to foreign network (roaming).
INFO - AModemDriver.connect(175) | GTW: modem.COM24: MEM: Storage Locations Found: SMBM
INFO - CNMIDetector.getBestMatch(142) | CNMI: No best match, returning: 1
INFO - ModemGateway.startGateway(191) | GTW: modem.COM24: Gateway started.
INFO - SmsHandler.readSMS(113) | read SMS size: 1
发信人:8618918001030 短信内容:hello 回复测试

INFO - ModemGateway.stopGateway(197) | GTW: modem.COM24: Stopping gateway...
INFO - SerialModemDriver.disconnectPort(120) | GTW: modem.COM24: Closing: COM24 @9600
INFO - ModemGateway.stopGateway(201) | GTW: modem.COM24: Gateway stopped.
INFO - SmsHandler.destroy(72) | SMS service stop
-----------

你可能感兴趣的:(java)