用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



附件提供相关下载:


本次测试的环境是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


1. package
2.     
3. import
4.     
5. import
6. import
7. import
8.     
9. /**
10.  * @author michael
11.  * 
12.  */
13. public   class
14.     
15. /**
16.      * @param args
17.      * @throws Exception
18.      */
19. public   static   void  main(String[] args)  throws
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
34. "com.sun.comm.Win32Driver"
35. "win32com"
36. null
37. try
38. "win32com"
39. " Library Loaded"
40.     
41.              commDriver = (javax.comm.CommDriver) Class.forName(driverName)   
42.                      .newInstance();   
43.              commDriver.initialize();   
44. "comm Driver Initialized"
45.     
46. catch
47.              System.err.println(e);   
48.          }   
49.      }   
50.     
51. /**
52.      * 获取端口列表
53.      */
54. public   static   void
55.          CommPortIdentifier portId;   
56.          Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();   
57. while
58.              portId = (CommPortIdentifier) portEnum.nextElement();   
59.     
60. if
61. "串口: name-"
62. " 是否占用-"
63. else
64. "并口: name-"
65. " 是否占用-"
66.              }   
67.          }   
68. "-------------------------------------"
69.      }   
70.     
71. /**
72.      * 
73.      */
74. public   static   void
75.     
76. "com.sun.comm.Win32Driver"
77. "win32com"
78. null
79. try
80. "win32com"
81. " Library Loaded"
82.     
83.              commDriver = (CommDriver) Class.forName(driverName).newInstance();   
84.              commDriver.initialize();   
85. "comm Driver Initialized"
86.     
87. catch
88.              System.err.println(e);   
89.          }   
90. null
91. try
92.     
93. "COM24"
94.                      CommPortIdentifier.PORT_SERIAL);   
95. "find CommPort:"
96. catch
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 
 
 
1. package
2.     
3. import
4. import
5. import
6.     
7. import
8. import
9.     
10. /**
11.  * @author michael
12.  * 
13.  */
14. public   class
15. static
16. static
17. static   int  bauds[] = {  9600 ,  19200 ,  57600 ,  115200
18.     
19. /**
20.      * @param args
21.      */
22. public   static   void
23.          portList = CommPortIdentifier.getPortIdentifiers();   
24. "GSM Modem 串行端口连接测试开始..."
25. "COM24"
26. while
27.              portId = (CommPortIdentifier) portList.nextElement();   
28. if
29.                      && portName.equals(portId.getName())) {   
30. "找到串口: "
31. for  ( int  i =  0
32. "  Trying at "  + bauds[i] +  "..."
33. try
34.                          SerialPort serialPort;   
35.                          InputStream inStream;   
36.                          OutputStream outStream;   
37. int
38. new
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. 1000
49.                          c = inStream.read();   
50. while  (c != - 1
51.                              c = inStream.read();   
52.                          }   
53. 'A'
54. 'T'
55. '\r'
56. try
57. 1000
58. catch
59.                          }   
60.                          c = inStream.read();   
61. while  (c != - 1
62. char
63.                              c = inStream.read();   
64.                          }   
65. if  (response.indexOf( "OK" ) >=  0
66. "  正在检测设备:"
67. try
68. 'A'
69. 'T'
70. '+'
71. 'C'
72. 'G'
73. 'M'
74. 'M'
75. '\r'
76. new
77.                                  c = inStream.read();   
78. while  (c != - 1
79. char
80.                                      c = inStream.read();   
81.                                  }   
82. "  发现设备: "
83.                                          + response.toString().replaceAll(   
84. "(\\s+OK\\s+)|[\n\r]" ,  ""
85. catch
86. "  检测设备失败,获取设备信息异常:"
87.                                          + e.getMessage());   
88.                              }   
89. else
90. "  检测设备失败,沒有接收到响应结果!"
91.                          }   
92.                          serialPort.close();   
93. catch
94. "  检测设备失败,发生异常:"
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...  发现设备失败,沒有接收到响应结果! 
  
 

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