获取验证码几乎是每个应用所必备的,很多应用在用户注册的时候设置一个验证码的功能,根据手机号获取验证码的作用就是防止恶意注册。先来看一下效果图
上面的效果就是读取短信的信息,然后根据信息内容将验证码截取出来,赋值到输入框。具体的实现过程如下:
首先就是要读取短信,获取短信的内容,如何获取短信的内容呢,android将所有的短信信息都存入了mmssms.db中,如果要访问短信数据库里面的内容就需要一些协议了
content://sms/inbox 收件箱
content://sms/sent 已发送
content://sms/draft 草稿
content://sms/outbox 发件箱
content://sms/failed 发送失败
content://sms/queued 待发送列表
根据上面的协议以及内容我们就知道,我们需要的tent://sms/inbox这个协议,因为我们的验证码是在收件箱里面的
cursor=MainActivity.this.managedQuery(Uri.parse("content://sms/inbox"),
new String[]{"_id", "address", "read", "body"},
"address=? and read=?", new String[]{"10690XXXXX", "0"}, "_id desc");//按id排序
if (cursor!=null&&cursor.getCount()>0){
ContentValues values=new ContentValues();
values.put("read", "1");//修改短信为已读模式
cursor.moveToNext();
int smsbodyColumn=cursor.getColumnIndex("body");
String smsBody=cursor.getString(smsbodyColumn);
}
要注意10690XXXXX这个是你接收验证码的号码,也就是发送验证码那一方的号码,而不是本人的手机号码。
下面是数据库的字段以及说明
_id 一个自增字段,从1开始
thread_id 序号,同一发信人的id相同
address 发件人手机号码
person 联系人列表里的序号,陌生人为null
date 发件日期
protocol 协议,分为: 0 SMS_RPOTO, 1 MMS_PROTO
read 是否阅读 0未读, 1已读
status 状态 -1接收,0 complete, 64 pending, 128 failed
type
ALL = 0;
INBOX = 1;
SENT = 2;
DRAFT = 3;
OUTBOX = 4;
FAILED = 5;
QUEUED = 6;
body 短信内容
service_center 短信服务中心号码编号
subject 短信的主题
reply_path_present TP-Reply-Path
locked
根据数据库中的字段以及说明我们就可以知道上面代码的作用了,上面的代码作用就是读取短信内容的。获取到短信内容以后我们还不算完成任务,因为我需要的是验证码,当然了要想获取验证码短信的获取是必不可少的,因为我们的验证码就包含在短信的内容里面的,所以我们要把验证码从短信内容里面分离出来,如何分离呢?
public String getVerificationCode(String str){
Pattern pattern = Pattern.compile("(\\d{6})");
Matcher matcher=pattern.matcher(str);
String verificationCode;
if (matcher.find()) {
verificationCode = matcher.group(0);
return verificationCode;
}
return "";
}
就是根据验证码的位数来判断,Pattern.compile(“(\d{6})”)表示连续6位的数字,可以在这修改成自己想要的格式,如四位验证码就将6替换为4即可。我们还可以看到matcher.find(),这个find()是什么呢?find()方法是部分匹配,是查找输入串中与模式匹配的子串,而我们平时用的matches()则是全部查询匹配。还有就是matcher.group(0)这又是怎么回事呢?这就是正则表达式里面的组,关于组我们来说一下是什么意思
String str = "name LiuYongxiang Robert!";
Pattern pattern = Pattern.compile("Liu(Yong)(xiang)");
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
System.out.println("matcher.group(0)---------->" + matcher.group(0));
System.out.println("matcher.group(1)---------->" + matcher.group(1));
System.out.println("matcher.group(2)---------->" + matcher.group(2));
}
输出的的内容为
想必大家一看便知这组的作用了。Pattern.compile(“Liu(Yong)(xiang)”)这个方法里面的一个()代表一个组。还有就是LiuYongxiang这个内容之间是不能有空格的,除非你匹配的时候也有空格,所要的内容和要匹配的内容完全一致才能匹配成功。前面讲了如何获取短信内容和验证码,但是还要注意,我们要获取的短信的内容可不是之前的,而是我们点击获取验证码后获取的短信内容。这一点想必大家都清楚。这样的话我们就需要一个内容观察者,时时刻刻监视着短信内容的变化,而这个观察者就是ContentObserver。继承ContentObserver要重写onChange这个方法,这个方法的作用就是监听短信内容是否发生了变化。
class SmsContentObserver extends ContentObserver {
private Cursor cursor;
public SmsContentObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//读取收件箱中指定号码的短信
try {
cursor=MainActivity.this.managedQuery(Uri.parse("content://sms/inbox"),
new String[]{"_id", "address", "read", "body"},
"address=? and read=?", new String[]{"10690XXXXX", "0"}, "_id desc");//按id排序
if (cursor!=null&&cursor.getCount()>0){
ContentValues values=new ContentValues();
values.put("read", "1");//修改短信为已读模式
cursor.moveToNext();
int smsBodyColumn=cursor.getColumnIndex("body");
String smsBody=cursor.getString(smsBodyColumn);
final String code = getVerificationCode(smsBody);
Message msg = new Message();
msg.what = VERIFICATION_CODE;
msg.obj = code;
mHandler.sendMessage(msg);
}
}catch (Exception e){
}
//在用managedQuery的时候,不能主动调用close()方法,否则在Android 4.0+的系统上会发生崩溃
if (Build.VERSION.SDK_INT<14){
cursor.close();
}
}
}
有了这些还是不够的,既然是观察者当然少不了注册,下面是注册的代码
SmsContentObserver smsContentObserver = new SmsContentObserver(mHandler);
Uri smsUri = Uri.parse("content://sms");
getContentResolver().registerContentObserver(smsUri, true, smsContentObserver);
如有疑问欢迎留言,如果感觉对您有帮助还请给个好评再走。