终于完成了用Java操作手机的模块,遇到了不少麻烦,在这里总结一下,也希望对大家有所帮助。
可能有很多人会问,现在的手机与计算机连接都是USB口,那研究串口手机通讯有什么意义?我开始也是这样考虑,所以在网上直接搜索USB端口通讯的JAVA开发包,像JUSB、Lib-usb就是专门对USB端口进行操作的。不过很可惜,他们都声明不支持windows操作系统,只能放弃。好几天也没有找到解决办法,到时有不少关于串口操作手机的操作方法,但我希望的是对USB端口进行操作。一个偶然的机会,发现“设备管理器”中的“端口”显示出我的手机设备名为“XXXX(COM3)。重要的是括号中的COM3,这会不会是说,已经把USB端口映射成为COM3?抱着试试的想法,从网上找到串口操作的使用方法,按照步骤一步一步,结果成功了,兴奋之情溢于言表,真是踏破铁鞋无觅处,得来全不费工夫啊,思索如何通过USB端口操作手机好几天都无果而终,没想到竟然可以通过串口操作,而且操作方式如此简单。
费了那么多话,下面就开始介绍Java操作手机收发短信的步骤。
1、 操作串口
从网上下载Java串口驱动,这个很简单,我的是javacomm20-win32.zip,其中包括:用到comm.jar、win32com.dll和javax.comm.properties三个文件。
这三个文件,windows开发与web开发放置的位置不同:
windows:将comm.jar和javax.comm.properties放到程序扩展包路径下(如/lib);win32com.dll放到程序根目录(或windows/system32下,或Java的bin目录下)。
web(Tomcat):comm.jar放到%JAVA_HOME%/jre/ib/ext/目录下;win32com.dll放到%JAVA_HOME%/bin目录下;javax.omm.properties放置到%JAVA_HOME%/jre/lib目录下。
串口的操作方法非常简单,通过下面这段代码就可以理解:
/**
* 取得端口
*/
public CommPort getCommPort() {
CommPort cp = null;
try {
CommPortIdentifier cpi = CommPortIdentifier.getPortIdentifier("COM3");
if(cpi != null) {
cp = cpi.open("SerialPort", 2000);
if(cp != null && cp instanceof SerialPort) {
SerialPort sp = (SerialPort)cp;
sp.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); //设置流控制
sp.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); //设置串口参数(速率,数据位,停止位,奇偶校验)
}
}
} catch(NoSuchPortException e) {
e.printStackTrace();
} catch(PortInUseException e) {
e.printStackTrace();
} catch(UnsupportedCommOperationException e) {
e.printStackTrace();
}
return cp;
}
/**
* 取得输入流
*/
public InputStream getInputStream() {
InputStream is = null;
CommPort cp = getCommPort();
if(cp != null) {
try {
is = cp.getInputStream();
} catch(IOException e) {
e.printStackTrace();
}
}
return is;
}
public OutputStream getOutputStream() {
OutputStream os = null;
CommPort cp = getCommPort();
if(cp != null) {
try {
os = cp.getOutputStream();
} catch(IOException e) {
e.printStackTrace();
}
}
return os;
}
2、 操作手机
明白了java串口通讯的方法,接下来要了解对手机的通讯方式。
目前,大多数手机都是使用AT命令进行操作的。AT命令有两种模式,即:TEXT模式和PDU模式,TEXT模式只能处理字母、数字等字符,所以英美等国家都使用这种模式,如果需要处理中文,必须使用PDU模式。我们使用的大多数手机同时支持两种模式。
下面将介绍常用的一些AT命令:我主要以举例的方式描述(默认为PDU模式)
在介绍AT命令之前,首先讲一下PDU模式对手机号码(或短信中心号码)的编码方式,后面简称为PDU编码。号码如果为奇数,则在号码后面增加一个F字符,然后对每两位的字符进行对调。比如:13812345678这个短信中心号码,编码后为3118325476F8。
1) 测试
如果要测试设备是否支持AT命令,可以使用:AT+/r。如果支持返回OK,否则返回ERROR。
2)模式设置:CMGF
手机可以自动判断短信内容使用何种模式编码发送,但如果我们要使用程序操作手机,则必须先将手机设置为正确的模式。
AT+CMGF?/r命令返回手机当前模式,1表示TEXT模式,0表示PDU模式。
AT+CMGF=<NUM>/r命令设置模式,<NUM>为0或1。
3)发短信:CMGS(只介绍PDU模式)
普通短信例子:AT+CMGS=17\r >0891683108100005F031000d91683118341528F100080002597d^z\r\n
长短信例子:
第一条:AT+CMGS=26\r > 0071000B813118911028F10008AA0C0500030402014F60597DFF01
第二条:AT+CMGS=26\r > 0071000B813118911028F10008AA0C0500030402024F60597DFF01
格式:AT+CMGS=
{数据长度}\r >
{短信中心号码}{PDU类型}00{接收手机号码长度}{号码格式}{手机号码}0008{数据头类型}{数据长度}{数据头}
{数据
}^z
\r\n
数据长度:表示从“PDU类型”到“数据”的长度除以2,如果长度为奇数,则为长度减1除以2。如例中为从31到597d
短信中心号码:
<1> 使用SIM卡默认短信中心号码:00
<2> 使用指定的短信中心号码,格式为:
{短信中心号码长度}
{号码格式}
{短信中心号码PDU编码}
短信中心号码长度:(“号码格式”+“号码PDU编码”)/ 2
号码格式:在下面介绍。
短信中心号码PDU编码:同“手机号码”
PDU类型:(理解的含义可能不是十分确切)
11:70个字以内的短信,无短信报告
31:70个字以内的短信,有短信报告
51:长短信(多条合并),无短信报告
71:长短信(多条合并),有短信报告
00:固定,不知含义
接收手机号码长度:接收手机号码长度
号码格式
:
91表示国际格式(需要在手机号码前加86),81表示国内格式
手机号码:接收手机号码。如果位数为奇数,在后面加一个F,然后每两位调换位置
00
:固定,不知含义
08:固定,不知含义
数据头类型:
00:无数据头
AA:具体含义不详,用于发送长短信。
数据长度:(“数据头”+“数据”) / 2
数据头:
<1> 如果数据头类型为00,没有数据头
<2> 发送长短信,包含:
{数据头长度}
{短信类型}
{分拆数据元素长度}
{标识}
{分拆信息总数}
{当前短信编号}
数据头长度:“短信类型”+“分拆数据元素长度”+“标识”+“分拆信息总数”+“当前短信编号”的总长度
短信类型:00表示分拆类型,详细的含义不清楚。
标识:用于接收端合并短信,判断那几条短信属于一条拆分的。
分拆短信总数:表示将一条短信分拆成几条
当前短信编号:表示当前短信是分拆短信中的第几条,起始为1
数据:Unicode编码的短信内容。中文直接是Unicode编码后的四位十六进制值,英文或字符在前面添加00补充成四位。例如:“好”编码为597d
^z::表示结束。(char)0x1a
如果发送成功,返回+CMGS: 185 OK。185表示短信编号,短信报告以此编号确定是哪条短信的短信报告。
如果要求短信报告,收到短信时会收到CDS的AT命令。
4)设置短信处理方式:CNMI
CNMI命令用于设置当接受到某类短信息时的处理方式。
AT+CNMI=<mode><mt><bm><ds><bfr>/r
<mode>控制通知TE的方式:
0——先将通知缓存起来,再按照<mt>的值进行发送。
1——在数据线空闲的情况下,通知TE,否则,不通知TE。
2——数据线空闲时,直接通知TE;否则先将通知缓存起来,待数据线空闲时再行发送。
3——直接通知TE。在数据线被占用的情况下,通知TE的消息将混合在数据中一起传输。
<mt>设置短消息存储和通知TE的内容:
0——接受的短消息存储到默认的内存位置(包括class 3),不通知TE。
1——接收的短消息储存到默认的内存位置,并且向TE发出通知(包括class 3)。通知的形式为:
+CMTI:”SM”,<index>
2——对于class 2短消息,储存到SIM卡,并且向TE发出通知;对于其他class,直接将短消息转发到TE:
+CMT:[<alpha>],<length><CR><LF><pdu>
或者+CMT:<oa>,[<alpha>,]<scts>[,,<tooa>,<fo>,<pid>,<dcs>,<sca>,,<tosca>,<length>]<CR><LF><data>(text模式)
3——对于class 3短消息,直接转发到TE,同<mt>=2;对于其他class,同<mt>=1。
<bm>设置小区广播方式:
0——小区广播不通知
2——新的小区广播通知,返回
+CBM:;length;;CR;;LF;;pdu;
3——Class3格式的小区广播通知,使用bm=2格式
<ds>状态报告
0——状态报告不通知
1——新的状态报告通知,返回:
+CDS:;length;;CR;;LF;;pdu;
2——如果新的状态报告存储到ME,则返回:
+CDSI:;mem;,;index;
<brf>
1——始终为1
5)短信报告:CDS
如果设置了短信报告通知,那么在对方收到短信后短信中心会返回一条短信报告,格式如下:
+CDS: 26 0006B90D91683118341528F1806050819290238060508192212300
B9:16进制短信编号,将其转换为十进制后与发短信时返回的短信编号相对应
0D:发送方手机号码长度
91
683118341528F
1:发送方手机号码(PDU编码)
806050819290
:发送时间
08-06-05
18
:
29
:
09
23
806050819221
:收到时间
08-06-05
18
:
29
:
12
23
00
:对方收到,如果对方无法收到返回
48
6)读短信:CMGR
设置好存储方式后用AT+CMGR=<index>/r命令读取短信息,index是短信编号(以1开始)。 如果是TEXT模式,返回:at+cmgr=1 +CMGR: "REC READ","+8613856907828",,"08/06/11,12:42:36+32" Hello
“REC READ”:短信已阅
"+8613856907828":发信方手机号码
"08/06/11,12:42:36+32":短信接收时间,32代表什么我不知道
Hello:短信内容 如果用PDU模式,返回:at+cmgr=1 +CMGR: 1,,24 0891683108100005F0240D91683167801368F100088060112144812302597D
08
91
683108100005F0:短信中心号码
24
0D:发送方手机号码长度(16进制)
91
683167801368F1:经过PDU编码的发送方手机号码13760831861
00
08:编码模式为PDU,否则为00,则需要用其他模式读取
806011214481:接收时间08-06-11 12:44:18
23
02:短信内容编码长度除以2(即597D长度 / 2)
597D:好的UniCode码
7)删除短信:CMGD
命令格式是:AT+CMGD=<index>/r。index为编号
如果删除成功,返回OK,否则返回ERROR。
以上就是我对串口操作手机短信内容的总结,希望能给更多的朋友提供帮助,也为自己今后再次使用时提供提供方便