/**稀土掘金,时光不老**/
大家好,最近做项目时,加了一个小功能,手机登录应用或注册时自动填写短信验证码,当然,网上有很多很棒的demo,我也来和大家分享一下,同时也作为一下个人笔记吧。
因为比较简单,就不上效果图了,为什么不用广播(BroadcastReceiver)来接收系统收到短信时候的广播。可是这个广播是有序广播,就是当别的程序先获取到了这个广播再传递给你,当然它也可以干掉这个广播,让你接收不到,这样你的程序肯定是接收不到这个广播的了。网上有很多这样的例子,什么提高广播接收器的优先级又是1000又是10000的。这里提到了把intent-filter中的android:priority的值设置为1000,但是在实时中你设置1000一样是接受不到广播的,除非你把手机中的其他接受了这个广播的短信卸载,比如360 GO短信,飞信神马的。他们的优先级总是要比你的高。你可以继续BAIDU,有的人会设置它为10000 9999等等,你会发现设置为10000的时候偶尔可以接收到,仅仅是偶尔。那肿么办呢。
大家可以看看这个广播的基本介绍:http://wenku.baidu.com/view/226f9dd5b14e852458fb57ba.html
好了,来说说几个核心点吧
1. 使用ContentObserver(使用的观察者模式)监听手机短信动态数据库,当收到短信数据库变化了的时候 去取得最新的那条短信即可。或者你想别的什么操作也可以。
2. 可指定一个号码,只读取与它有关短信,避免提取来源错误 。
3. 可过滤掉与我们不需要的短信
4. 利用正则表达式,可匹配各种类型验证码。
哈哈 ,激动人心的时刻来了,看代码--------------
这是获取短信验证码的工具类
public class SmsReciverUtil extends ContentObserver { private Activity c; private int codelength; private Handler handler; public SmsReciverUtil(Handler handler, Activity c, int codelength) { super(handler); this.c = c; this.codelength = codelength;//截取验证码的长度 this.handler = handler; } // 收到短信一般来说都是执行了两次onchange方法.第一次一般都是raw的这个.这个时候虽然收到了短信.但是短信还没有写入 到收件箱里面 // 然后才是另外一个,后面的数字是该短信在收件箱中的位置 @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); if (uri.toString().equals("content://sms/raw")) { return; } String code = getsmsCode(c, codelength); if (!TextUtils.isEmpty(code)) { // 利用handler将得到的验证码发送给主界面 Message msg = Message.obtain(); msg.what =0; msg.obj = code; handler.sendMessage(msg); } } public String getsmsCode(Activity c, int codelength) { ContentResolver contentresolver = c.getContentResolver(); // 设置一个uri来查看收件箱中短信内容 Uri uri = Uri.parse("content://sms/inbox"); //需要查询的字段 address 号码,read 0未读 1已读,body短信内容 String[] projection = new String[]{"_id", "address", "read", "body"}; //需要查询未读短信 // String selection = "address=? and read=?"; //注意这里填写的号码如何是公司里固定的号码可以是 (xxxxxxx)但是测试使用的号码时看有没有(+86xxxxxxx)别 写错了,代码没问题,好好检查O(∩_∩)O哈哈~,当然你可以不写需要查询的号码,查询收件箱数据库中的短信 // String [] selections = new String[]{"这里填写需要查询的号码","0"}; // 按短信id倒序排序,如果按date排序的话,修改手机时间后,读取的短信就不准了 String sortOrder = "_id desc"; // 读取收件箱中指定号码的短信 Cursor cur = contentresolver.query(uri, projection, null, null, sortOrder); if (null == cur) { return null; } if (cur.getCount() <= 0) { return null; } if (!cur.moveToFirst()) { return null; } String number = cur.getString(cur.getColumnIndex("address"));// 手机号 String body = cur.getString(cur.getColumnIndex("body"));//短信类容 // 最后用完游标千万记得关闭 cur.close(); // 在这里我们的短信提供商的号码如果是固定的话.我们可以再加一个判断,这样就不会受到别的短信应用的验证码的影响了 if (!number.startsWith("这里填写你的号码以xxxx开头的数字")) { return null; } if (!body.contains("这里填写你的过滤的名称"){ return null; } return getyzm(body, codelength); } /** * 从短信字符窜提取验证码 * * @param body 短信内容 * @param codelength 验证码的长度 一般4位 * @return 接取出来的验证码 */ public String getyzm(String body, int codelength) { Pattern p = Pattern.compile("(?<![0-9])([0-9]{" + codelength + "})(?![0-9])"); Matcher matcher = p.matcher(body); if (matcher.find()) { // ContentValues values = new ContentValues(); // values.put("read", "1"); // 修改短信为已读模式 return matcher.group(0); } return null; } }
哇 差点忘了,相信很多小伙伴们犯过这样的错误吧O(∩_∩)O哈哈~
<!-- 阅读消息 -->
<uses-permission android:name="android.permission.READ_SMS" />
<!-- 接收消息 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
如果你还有其他操作还要加上一些权限
<!-- 发送短信-->
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- 写入消息 -->就是这么简单对不demo就不写了呵呵这里很清楚也很简单..不喜勿喷,有错回帖
来一句 弘洋大神 的名言