一、为了减少用户的操作步骤,在获得短信验证码的时候,我们可以监听特殊手机号码的短信,截取信息当中的短信验证码(其实有很多应用都监听短信例如360短信,一些信用卡或者是记账类的应用)。
二、原理:可以使用一个自定义的BroadcastReceiver来监听短信,在监听结果当中过滤手机号,在需要回填的activity当中实现实例化广播并且实现其回调接口,在接口当中进行回填验证码,在销毁activity时销毁链接。但是这样操作会出现一些问题,由于一些其他的应用也会使用广播监听手机例如QQ通讯录或者是360通讯录等有的时候会被其拦截,即使你修改优先级也会出现不能进行回填的问题。所有这里可以采用另外一种的解决方法:使用ContentProvider来监听短信数据库的变化,在自定义的ContentObserver当中实现onChange的方法进行监听特定手机号的短信,然后进行信息截取在填充到需要填充的位置。
在AndroidManifest当中需要的权限:
<!-- 发送短信-->
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- 阅读消息 -->
<uses-permission android:name="android.permission.READ_SMS" />
<!-- 写入消息 -->
<uses-permission android:name="android.permission.WRITE_SMS" />
<!-- 接收消息 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
四、属性
/**属性*/
private SmsContent content = null;
private EditText edit1 = null;
五、在oncreate()方法中注册短信库的监听:
content = new SmsContent(new Handler());
//注册短信变化监听
this.getContentResolver().registerContetObserver(Uri.parse("content://sms/"), true, content);
六、在activity中的内部类:
/*
* 监听短信数据库
*/
class SmsContent extends ContentObserver {
private Cursor cursor = null;
public SmsContent(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@SuppressWarnings("deprecation")
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
super.onChange(selfChange);
// 读取收件箱中指定号码的短信
cursor = managedQuery(Uri.parse("content://sms/inbox"),
new String[] { "_id", "address", "read", "body" },
" address=? and read=?",
new String[] { "监听的号码", "0" }, "_id desc");
// 按id排序,如果按date排序的话,修改手机时间后,读取的短信就不准了
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);
edit1.setText(getDynamicPassword(smsBody));
}
// 在用managedQuery的时候,不能主动调用close()方法, 否则在Android 4.0+的系统上, 会发生崩溃
if (Build.VERSION.SDK_INT < 14) {
cursor.close();
}
}
}
/**
* 从字符串中截取连续6位数字组合 ([0-9]{" + 6 + "})截取六位数字 进行前后断言不能出现数字 用于从短信中获取动态密码
*
* @param str
* 短信内容
* @return 截取得到的6位动态密码
*/
public static String getDynamicPassword(String str) {
// 6是验证码的位数一般为六位
Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{"
+ 6 + "})(?![0-9])");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
System.out.print(m.group());
dynamicPassword = m.group();
}
return dynamicPassword;
}
七、
在Activity销毁的时候要记得关闭数据库监听:
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
this.getContentResolver().unregisterContentObserver(content);
}
备注:
private final String SMS_URI_ALL = "content://sms/";//所有的
private final String SMS_URI_INBOX = "content://sms/inbox"; // 收件箱
private final String SMS_URI_SEND = "content://sms/sent"; // 发件箱
private final String SMS_URI_DRAFT = "content://sms/draft"; // 草稿箱
这样既可以实现短信监听自动回填,在回填的位置一般使用EditText不要使用TextView,因为android手机用户可能会禁止应用访问短信的权限应该支持手动填写。