【android】利用ContentObserver监听短信来获取验证码

我们知道,可以通过注册广播的方法来读取短信,进而获取验证码,但实际应用起来是会有问题的,因为短信的广播是有序广播,假如有其他应用先捕获广播并终止传递,那么我们就永远也收不到这条短信变化的广播了。

所以,本文介绍的是一种更好的办法————————利用ContentObserver监听短信来获取验证码

先来点介绍性文字吧。

“ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关的。”

下面给出方案3的关键性代码:

1、AndroidManifest.xml文件中配置短信读取权限

<uses-permission android:name="android.permission.READ_SMS" />

2、监听短信变化的类

public class SmsContentObserver extends ContentObserver {
		private static final String TAG = "SmsContentObserver";
		//发送验证码的号码
		private static final String VERIFY_CODE_FROM = "106903331094102";
		//5位纯数字验证码
		private static final String PATTERN_CODER = "(?<!\\d)\\d{5}(?!\\d)";
		private Context mContext;
		private Handler mHandler;


		public SmsContentObserver(Context context, Handler handler) {
			super(handler);
			this.mContext = context;
			this.mHandler = handler;
		}


		@Override
		public void onChange(boolean selfChange) {
			Uri inBoxUri = Uri.parse("content://sms/inbox");
			Cursor c = mContext.getContentResolver().query(inBoxUri, null,
					null, null, "date desc");
			if (c != null) {
//				while (c.moveToNext()) {
				//只取最新的一条短信
				if (c.moveToNext()) {
					String number = c.getString(c.getColumnIndex("address"));//手机号
					Log.d(TAG, "number:"+number);
					String body = c.getString(c.getColumnIndex("body"));
					if (number.equals(VERIFY_CODE_FROM)) {
						String verifyCode = patternCode(body);
						Message msg = Message.obtain();
						msg.what = 1;
						msg.obj = verifyCode;
						mHandler.sendMessage(msg);
//						break;
					}
				}
				c.close();
			}
		}
		
		private String patternCode(String patternContent) {
			if (TextUtils.isEmpty(patternContent)) {
				return null;
			}
			Pattern p = Pattern.compile(PATTERN_CODER);
			Matcher matcher = p.matcher(patternContent);
			if (matcher.find()) {
				return matcher.group();
			}
			return null;
		}
	}

当短信有变化时,把短信内容读取出来,并按时间由高到低排序。根据自己项目需要的短信验证码的格式匹配(我这里的匹配方法写的很LOW,-_-||)。找到后,可以不用继续读取短信直接break。这里通过Handler的去更新UI。

3、注册/取消注册监听

通常是在onResum中去注册短信监听,在onStop中取消注册。

@Override
protected void onStop() {
    super.onStop();
    unRegisterSmsContentObservers();
}

@Override
protected void onResume() {
    super.onResume();
    registerSmsContentObservers();
}

private void registerSmsContentObservers() {
    Uri smsUri = Uri.parse("content://sms");
   //smsContentObserver是SmsContentObserver的一个实例,可以在onCreate中初始化
   getContentResolver().registerContentObserver(smsUri, true,smsContentObserver);
}

private void unRegisterSmsContentObservers() {   getContentResolver().unregisterContentObserver(smsContentObserver);
}

注意,虽然我们监听的是收件箱inbox,但是在注册时需要监听所有短信的变化。这句很重要:

Uri.parse("content://sms")

不能写成

Uri.parse("content://sms/inbox")

其实,通过ContentObserver还能做很多事情。更多功能等待大家去发现。

另外,附sms主要结构:
  
  _id:短信序号,如100
  
  thread_id:对话的序号,如100,与同一个手机号互发的短信,其序号是相同的
  
  address:发件人地址,即手机号,如+86138138000
  
  person:发件人,如果发件人在通讯录中则为具体姓名,陌生人为null
  
  date:日期,long型,如1346988516,可以对日期显示格式进行设置
  
  protocol:协议0SMS_RPOTO短信,1MMS_PROTO彩信
  
  read:是否阅读0未读,1已读
  
  status:短信状态-1接收,0complete,64pending,128failed
  
  type:短信类型1是接收到的,2是已发出
  
  body:短信具体内容
  
  service_center:短信服务中心号码编号,如+8613800755500

参考:http://www.jianshu.com/p/5ccdcd9bed89、http://blog.csdn.net/mad1989/article/details/22426415


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值